<!-- 实现登录验证和鉴权 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
/**
* spring security配置
* */
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//认证失败处理类
@Autowired
private AuthenticationEntryPointImpl unauthorizedHandler;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// csrf禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login允许匿名访问
.antMatchers("/login","/profile/avatar/**").anonymous()
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
.antMatchers("/profile/**").anonymous()
// 除了这些,都要授权
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
}
}
/**
* 认证失败处理类返回未授权
* */
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
int code = HttpStatus.UNAUTHORIZED;
String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
ServletUtils.renderString(response, JSON.toJSONString(RestResult.error(code,msg)));
}
}
package edu.friday.common.security.service;
import edu.friday.common.enums.UserStatus;
import edu.friday.common.exception.BaseException;
import edu.friday.common.security.LoginUser;
import edu.friday.model.SysUser;
import edu.friday.model.vo.SysUserVo;
import edu.friday.service.SysUserService;
import edu.friday.utils.BeanUtils;
import edu.friday.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/**
* 用户验证处理
* */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
@Autowired
private SysUserService userService;
@Autowired
private SysPermissionService permissionService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser user = userService.selectUserByUserName(username);
if(StringUtils.isNull(user)){
log.info("登录用户:{} 不存在.",username);
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
log.info("登录用户:{} 已被删除.",username);
throw new BaseException("对不起,您的账号:" + username + "已被删除");
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.",username);
throw new BaseException("对不起,您的账号:" + username + "已被停用");
}
return createLoginUser(user);
}
public UserDetails createLoginUser(SysUser user){
SysUserVo sysUserVo = new SysUserVo();
BeanUtils.copyProperties(user,sysUserVo);
return new LoginUser(sysUserVo,permissionService.getMenuPermission(sysUserVo));
}
}
package edu.friday.common.security;
import com.fasterxml.jackson.annotation.JsonIgnore;
import edu.friday.model.vo.SysUserVo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {
private static final long serialVersionUID = 1L;
/**
* 用户唯一标识
* */
private String token;
/**
* 登录时间
* */
private Long loginTime;
/**
* 过期时间
* */
private Long expireTime;
/**
* 登录IP地址
* */
private String ipaddr;
/**
* 登录地点
* */
private String loginLocation;
/**
* 浏览器类型
* */
private String browser;
/**
* 操作系统
* */
private String os;
/**
* 权限列表
* */
private Set<String> permissions;
/**
* 用户信息
* */
private SysUserVo user;
public LoginUser(SysUserVo user, Set<String> permissions) {
this.user = user;
this.permissions = permissions;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@JsonIgnore
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return null;
}
/**
* 账户是否过期,过期无法验证
* */
@Override
public boolean isAccountNonExpired() {
return false;
}
/**
* 指定用户是否解锁,锁定的用户无法进行身份验证
* */
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return false;
}
/**
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
*
* @return
*/
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return false;
}
/**
* 是否可用 ,禁用的用户不能身份验证
*
* @return
*/
@Override
public boolean isEnabled() {
return false;
}
}
/**
* 通过用户名称查找用户
* @param userName 用户名
* return 用户对象信息
* */
@Override
public SysUser selectUserByUserName(String userName) {
SysUser sysUser = new SysUser();
sysUser.setUserName(userName);
sysUser.setDelFlag("0");
Example<SysUser> example = Example.of(sysUser);
return findOne(example);
}
package edu.friday.common.security.service;
import edu.friday.model.vo.SysUserVo;
import edu.friday.service.SysMenuService;
import edu.friday.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
@Component
public class SysPermissionService {
@Autowired
private SysRoleService roleService;
@Autowired
private SysMenuService menuService;
/**
* 获取角色权限
* */
public Set<String> getRolePermission(SysUserVo user){
Set<String> roles = new HashSet<String>();
// 管理员拥有所有权限
if(user.isAdmin()){
roles.add("admin");
}else{
roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
}
return roles;
}
/**
* 获取菜单数据权限
*
* @param user 用户信息
* return 菜单权限信息
* */
public Set<String> getMenuPermission(SysUserVo user){
Set<String> roles = new HashSet<String>();
// 管理员拥有所有权限
if(user.isAdmin()){
roles.add("*:*:*");
}else{
roles.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
}
return roles;
}
}
@Override
public Set<String> selectRolePermissionByUserId(Long userId) {
List<SysRole> perms = sysRoleRepository.selectRoleByUserId(userId);
Set<String> permsSet = new HashSet<>();
for (SysRole perm:perms) {
if(StringUtils.isNotNull(perm)){
permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
}
}
return permsSet;
}
/**
* 根据用户id查询权限
* @param userId 用户id
*
* @return 权限列表
* */
@Override
public Set<String> selectMenuPermsByUserId(Long userId) {
List<String> perms = sysMenuRepository.selectMenuPermsByUserId(userId);
Set<String> permsSet = new HashSet<>();
for (String perm:perms){
if(StringUtils.isNotEmpty(perm)){
permsSet.addAll(Arrays.asList(perm.trim().split(",")));
}
}
return permsSet;
}
package edu.friday.repository.custom;
import edu.friday.model.SysMenu;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface SysMenuRepository extends JpaRepository<SysMenu,Long> {
final String JOIN_ROLE_MENU = " left join sys_role_menu rm on m.menu_id = rm.menu_id ";
final String JOIN_USER_ROLE = " left join sys_user_role ur on rm.role_id = ur.role_id ";
@Query(value = " select distinct m.perms from sys_menu m" + JOIN_ROLE_MENU + JOIN_USER_ROLE
+ " where ur.user_id = :userId", nativeQuery = true)
List<String> selectMenuPermsByUserId(@Param("userId") Long userId);
}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号