文章目录
Spring Security
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。 Spring Security是一个框架,致力于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring Security的真正强大之处在于可以轻松扩展以满足自定义要求
JWT无状态的单点登录
jwt生成的token有有效期,如果没有到有效期怎么让token失效?
用户每次登录都把token对应保存到redis(username,token)
每次判断token是否有效,有效再次判断token是否和redis是否一致,不一致则token失效
流程
- 注册 username,password(加密后的)存到数据库
- 登录 通过username 和 password 比较判断是否正确,正确返回用户信息 token(jwt生成)
- 访问(需要传入token)通过token生成对应的UsernamePasswordAuthenticationToken并设置到SecurityContext
中去- 设置某一个方法的访问权限
@PreAuthorize(“hasAuthority(‘ROLE_XYZ’)”)与@PreAuthorize(“hasRole(‘XYZ’)”)相同
用到的方法
configure(HttpSecurity http)
http.cors()
.and()
// 关闭csrf
.csrf().disable()
// 关闭session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.accessDeniedHandler(deniedHandler)
.authenticationEntryPoint(entryPoint)
.and()
.authorizeRequests()
// 需要角色为ADMIN才能删除该资源
.antMatchers(HttpMethod.DELETE, "/tasks/**").hasAnyRole(ROLE_ADMIN)
// 测试用资源,需要验证了的用户才能访问
.antMatchers("/tasks/**").authenticated()
// 其他都放行了
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/api/user/login")
.usernameParameter("user")
.passwordParameter("pwd")
.successHandler(successHandler)
.failureHandler(failureHandler)
.permitAll()
.and()
.logout()//默认注销行为为logout
.logoutUrl("/api/user/logout")
.logoutSuccessHandler(logoutSuccessHandler)
.and()
// 添加到过滤链中
// 先是UsernamePasswordAuthenticationFilter用于login校验
// 再通过OncePerRequestFilter,对其他请求过滤
.addFilter(new JwtPreAuthFilter(authenticationManager(), getJwtTokenUtil()));
登录 authenticationSuccessHandler loadUserByUsername
http://127.0.0.1:8087/api/user/login
//匹配
List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
simpleGrantedAuthorities.add(new SimpleGrantedAuthority(ROLE_ADMIN));
AdminUser user = AdminUser.getInstance();
return new User(user.getUsername(), user.getPassword(), simpleGrantedAuthorities);
//返回数据
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
String s = JwtTokenUtil.TOKEN_PREFIX+jwtTokenUtil.generateToken(SecurityUtils.getCurrentUser());
response.getWriter().write(JSONObject.toJSONString(RUtil.success(AdminUser.getInstance().setToken(s))));
通过token访问 doFilterInternal
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
String tokenHeader = request.getHeader(JwtTokenUtil.TOKEN_HEADER);
System.out.println("tokenHeader:" + tokenHeader);
// 如果请求头中没有Authorization信息则直接放行了
if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtil.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
// 如果请求头中有token,则进行解析,并且设置认证信息
SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
super.doFilterInternal(request, response, chain);
}
/**
* description: 读取Token信息,创建UsernamePasswordAuthenticationToken对象
*
* @param tokenHeader
* @return org.springframework.security.authentication.UsernamePasswordAuthenticationToken
*/
private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) {
//解析Token时将“Bearer ”前缀去掉
String token = tokenHeader.replace(JwtTokenUtil.TOKEN_PREFIX, "");
String username = jwtTokenUtil.getUserNameFromToken(token);
List<String> roles = jwtTokenUtil.getUserRole(token);
Collection<GrantedAuthority> authorities = new HashSet<>();
if (roles != null) {
for (String role : roles) {
// authorities.add(new SimpleGrantedAuthority(ROLE_PRE+role));
//hasRole('admin')
//hasAuthority('admin')
//@PreAuthorize("hasAuthority('ROLE_XYZ')")与@PreAuthorize("hasRole('XYZ')")相同
authorities.add(new SimpleGrantedAuthority(role));
}
}
if (username != null) {
return new UsernamePasswordAuthenticationToken(username, null, authorities);
}
return null;
}
方法设置权限
@ApiOperation(value = "测试权限接口hasAuthority")
@PostMapping(value = "/testPreAuthorize")
@PreAuthorize("hasAuthority('admin')")
public R<String> testPreAuthorize() {
return RUtil.success("admin" + SecurityContextHolder.getContext().getAuthentication().getPrincipal());
}
@ApiOperation(value = "测试权限接口")
@PostMapping(value = "/testPreAuthorizeRole")
@PreAuthorize("hasRole('admin')")
public R<String> testPreAuthorizeRole() {
return RUtil.success("admin" + SecurityContextHolder.getContext().getAuthentication().getPrincipal());
}
来源:CSDN
作者:yujunlong3919
链接:https://blog.csdn.net/yujunlong3919/article/details/103481152