SpringSecurity
2022-9-3 大约 2 分钟
# SpringSecurity
# 认证(Authentication)
# 未注入security配置默认过滤器
# security + jwt
原理:放行/login请求,登录后返回jwt token,主配置类中追加过滤器判断jwt是否有效,若无效直接被exceptionHandling捕获异常, 若有效则获取jwt中用户信息(不包含密码)及获取该用户redis中的权限,通过UsernamePasswordAuthenticationToken构建对象设置到上下文中。
主配置类
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.and()
//禁止网页iframe
.headers().frameOptions().disable().and()
//任何请求需要身份认证
.authorizeRequests().anyRequest().authenticated().and()
//允许跨域
.cors().configurationSource(new corsFilter()).and()
//关闭跨站请求防护
.csrf().disable()
//前后端分离采用JWT 不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
//权限拒绝处理类
.exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()
//认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
//添加JWT认证过滤器
.addFilter(new JwtAuthenticationTokenFilter())
//可以通过api
.antMatchers("/login").permitAll();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
jwt过滤器
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{
@Autowired
private TokenService tokenService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException
{
LoginUser loginUser = tokenService.getLoginUser(request);
// 每一次请求Authentication为null
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityContextHolder.getContext().getAuthentication()))
{
tokenService.verifyToken(loginUser);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
chain.doFilter(request, response);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
生成的过滤器
# 授权(Authorization)
# 原理:根据UsernamePasswordAuthenticationToken配置用户权限,通过以下注解对api进行限制
- anyRequest | 匹配所有请求路径
- access | SpringEl表达式结果为true时可以访问
- anonymous | 匿名可以访问
- denyAll | 用户不能访问
- fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
- hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
- hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
- hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
- hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
- hasRole | 如果有参数,参数表示角色,则其角色可以访问
- permitAll | 用户可以任意访问
- rememberMe | 允许通过remember-me登录的用户访问
- authenticated | 用户登录后可访问
# 使用例子
@RestController
@RequestMapping("/money")
public class MoneyController extends BaseController {
@GetMapping("/info/{id}")
@PreAuthorize("hasAuthority('money:update')")
public Result info(@PathVariable("id") Long id) {
Money money = moneyService.findById(id);
return Result.succ(money);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12