Springboot+Spring secuirty 后台菜单权限设计
2021-01-29 17:15
标签:art 用户信息 real 获取用户信息 html list tpm grant exception 背景:菜单和权限在系统中是非常重要的事情,在结合自己研究过的Spring security和项目前后端实践中对进行总结。 介绍:使用基于RBAC权限模型,针对角色分配不同的权限 数据库设计: 系统菜单 系统角色 菜单角色表 用户对应的角色 用户信息 技术:Spring security+jjwt Spring security:是Spring 开源的权限管理框架,由一组过滤器链组成,对不同的访问进去拦截和控制,也可以自己实现权限拦截 spring security 的核心功能主要包括: jjwt:是一个提供端到端的JWT创建和验证的Java库,可以生成加密的token,并可以从token反推出存放在token的一些信息(如用户账号)——参考官网https://jwt.io/introduction/ 实现:通过UserDetailsService 和UserDetails 通过数据库获取用户信息如(权限,用户账号) 步骤一: 步骤二:实现 UserDetailsService 接口,这里我使用mybatis查询数据库,通过用户账号获取数据库用户信息 步骤三:JwtPermissionService 实现,请注意这是实现的虚假逻辑,具体的还要看业务逻辑 步骤4:定义Spring security 权限配置 步骤4:自定义拦截器,通过此拦截器, 前端访问时候头部要带"Authorization",通过token获取用户信息 步骤五:登录返回toekn 给前端 步骤6 定义具有某个菜单的构造器,前端通过定义菜单标识跟后台@PreAuthorize 对应的权限进行关联起来,这样就可以形成对应的权限 Springboot+Spring secuirty 后台菜单权限设计 标签:art 用户信息 real 获取用户信息 html list tpm grant exception 原文地址:https://www.cnblogs.com/uqing/p/12831065.html
// 定义jjwt的用户的一些信息,在后面生成token时需要,并且Spring security要获取实现UserDetails 接口用户信息
@Getter
@AllArgsConstructor
public class SystemUser implements UserDetails {
@JSONField(serialize = false)
private final Long id;
private final String username;
@JSONField(serialize = false)
private final String password;
public Long getId() {
return id;
}
private final String salt;
// 权限
@JSONField(serialize = false)
private final Collectionpublic class SystemUserDetailsService implements UserDetailsService {
@Autowired
private ISysUserService userService;
@Autowired
private JwtPermissionService permissionService; // 获取用户角色的菜单权限
@Override
public UserDetails loadUserByUsername(String username) {
SysUser user = userService.findByName(username);
if (user == null) {
throw new ServiceException("账号不存在");
} else {
if (user.getUserStatus().equals(Constants.OrganizationStatus.DISABLE)) {
throw new ServiceException("账号已被禁用");
}
return createJwtUser(user);
}
}
public UserDetails createJwtUser(SysUser user) {
return new SystemUser(
user.getId(),
user.getUsername(),
user.getPassword(),
user.getSalt(),
permissionService.mapToGrantedAuthorities(user),
user.getCreateTime()
);
}
}
@Component
public class JwtPermissionService{
@Autowired
private IUsersRolesService usersRolesService;@Autowired
private IRolesMenuService rolesMenuService;
public Collection
// step 1 根据用户账号获取用户的角色
Set
// step 2 根据角色获取用户的菜单
Set // step 3 获取菜单对应的menu_make 进行转换
return menuVos.stream().filter(x -> !StringUtils.isEmpty(x.getMenuMark())).map( result -> {
String permission =result.getMenuMark();
return new SimpleGrantedAuthority(permission); }
).collect(Collectors.toList());}
}@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtTokenFilter tokenFilter;@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoderBean());
}@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
// 去掉前缀
return new GrantedAuthorityDefaults("");
}
// 加密方式@Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}// 权限拦截规则,千万不要.login() 这直接走表单验证了,会比较麻烦 @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// 禁用 CSRF
.csrf().disable()
// 不创建会话
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).anonymous()
.antMatchers( HttpMethod.POST,"/auth/login).permitAll()
.antMatchers("/websocket/**").anonymous()
// 所有请求都需要认证
.anyRequest().authenticated()
// 防止iframe 造成跨域
.and().headers().frameOptions().disable();
// 添加自定义拦截器
httpSecurity
.addFilterBefore(tokenFilter,UsernamePasswordAuthenticationFilter.class); }}
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String requestHeader = request.getHeader("Authorization");
String authToken=null;
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
authToken = requestHeader.substring(7);
String userName =Jwts.parser().setSigningKey(secret).parseClaimsJws(authToken ).getBody().getSubject();
}if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
SystemUser userDetails = (SystemUser ) this.userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);chain.doFilter(request, response);
}
}
}@Getter
@AllArgsConstructor
public class AuthenticationInfo implements Serializable {
private final String token;
private final JwtUser user;
}
// 登录构造器
@RequestMapping("auth")
public class SecurityController{@Autowired
@Qualifier("SystemUserDetailsService")private UserDetailsService userDetailsService;
@PostMapping(value = "${jwt.auth.path}")
public AuthorizationUser login(@RequestParam("userName")String userName,@RequestParam("password")String password)) { final SystemUser jwtUser = (SystemUser ) userDetailsService.loadUserByUsername(userName);
//获取用户的token,是否存在
Date expirationDate = new Date(createdDate.getTime() +864000);
String token =Jwts.builder()
.setClaims(claims)
.setSubject()
.setIssuedAt(new Date)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
return new AuthenticationInfo(token, jwtUser));
}
}@RequestMapping("/admin")
public class Demo {
@RequestMapping("/pageList")
@PreAuthorize("hasAnyRole(‘menu_mark’)")
public List
SystemUser
上一篇:Java 之反射
文章标题:Springboot+Spring secuirty 后台菜单权限设计
文章链接:http://soscw.com/index.php/essay/48778.html