我们在使用spring security和 Jwt结合使用的时候,对特殊路径设置权限时肯能会有不同的效果
anonymous:这个表达式用于指定某个资源或服务只能被匿名用户访问,,一旦用户通过了登录认证流程(例如,用户携带有效的token信息请求资源),该用户将不能再访问被标记为.anonymous()的资源。
permitAll:此表达式指示资源对所有用户开放,无论他们是否经过了身份验证。换句话说,它允许匿名用户和已登录用户都能够访问相关的资源。
我们先看一个security配置这个配置对 以下路径有特殊处理
"/api/user/register","/api/user/login1","/api/upload/write"
@Configuration
@EnableWebSecurity //开启spring security,可以省略
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); //禁用跨域功能
http.logout().disable(); //禁用注销功能
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//禁用session功能
http .authorizeRequests()
.antMatchers("/api/user/register","/api/user/login1","/api/upload/write").permitAll() //antMatchers可以精细化配置
.anyRequest().authenticated(); //除了上面的配置以外,所有的请求都需要认证
http.addFilter(new TokenFilter(this.authenticationManager())); //把token里面的角色方法SecurityContextHolder里面
http.exceptionHandling().authenticationEntryPoint((request,response,authException)->{
response.setContentType("application/json; charset=utf-8");
response.getWriter().write("{'code':403,'msg':'权限不足'}");
});
}
public static class TokenFilter extends BasicAuthenticationFilter {
public TokenFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String token = request.getHeader("token");
if(ObjUtil.isNotEmpty(token)){
//存储在ThreadLocal的token身份
LocalUser localUser = JSONUtil.toBean(JWTUtil.parseToken(token).getPayload().toString(),LocalUser.class);
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
String[] roles = localUser.getRoles();
for (String role : roles) {
//ROLE_ 一定要加上,否则会报错,它是为了兼容老的规则
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_"+role));
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
localUser.getId(), // 用户名
"",
grantedAuthorities
); // 角色列表
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
}
}
anonymous在使用时遇到的问题:如果使用anonymous登录系统,token的有效期过期之后会自动返回登录页面,但是此时是以aonoymous登入系统的,JWT不会清除token,再次登录会携带之前已经过期的token,但是token已经过期,
后台会报token有效期的错误。
浏览器登录页面就不能再次访问被标记的资源
解决办法:将anonymous()更改为permitAll()即可