使用spring security,我已经看过类似的问题,但他们说尝试禁用cors & csrf。
我在浏览器上使用它,所以我需要csrf。但是仅仅简单的测试并不能改变结果。
登录时,我会获得一个访问令牌和刷新令牌。
使用此令牌会给我一个403禁止响应代码。
我的配置如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/login").permitAll();
http.authorizeRequests().antMatchers(GET, "/**").hasAnyAuthority("STUDENT");
http.authorizeRequests().anyRequest().authenticated();
http.addFilter(new CustomAuthenticationFilter(authenticationManagerBean()));
http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
我想这可能与这个过滤器有关,但如果我将forbidden.value
更改为其他内容,结果仍然是forbidden.value
public class CustomAuthorizationFilter extends OncePerRequestFilter { // INTERCEPTS EVERY REQUEST
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(request.getServletPath().equals("/login")){ filterChain.doFilter(request,response); } // DO NOTHING IF LOGGING IN
else{
String authorizationHeader = request.getHeader(AUTHORIZATION);
if(authorizationHeader != null && authorizationHeader.startsWith("Bearer ")){
try {
String token = authorizationHeader.substring("Bearer ".length()); // TAKES TOKEN STRING AND REMOVES BEARER
// THIS NEEDS MAKING SECURE AND ENCRYPTED vvvvvvv
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes()); // <<<<<<<<<<<<<<<<<<<<<<<
JWTVerifier verifier = JWT.require(algorithm).build(); // USING AUTH0
DecodedJWT decodedJWT = verifier.verify(token);
String email = decodedJWT.getSubject(); // GETS EMAIL
String[] roles = decodedJWT.getClaim("roles").asArray(String.class); // GETS ROLES
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
stream(roles).forEach(role -> { authorities.add(new SimpleGrantedAuthority(role)); }); // CONVERTS ALL USERS ROLE INTO AN AUTHORITY
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(email, null); // PASSWORD IS NULL AT THIS POINT
SecurityContextHolder.getContext().setAuthentication(authToken); // INSERTS TOKEN INTO CONTEXT // THIS SHOWS AUTHENTICATED FALSE, DETIALS FALSE AND GRANTED AUTHORITIES EMPTY
filterChain.doFilter(request, response); // GETS TO THIS LINE HERE
}
catch (Exception e){
response.setHeader("error" , e.getMessage() );
response.setStatus(FORBIDDEN.value());
Map<String, String> error = new HashMap<>();
error.put("error_message", e.getMessage());
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), error); // THEN SKIPS RIGHT TO THIS LINE HERE EVEN IF BREAKPOINTING BEFORE
}
}
else{ filterChain.doFilter(request, response); }
}
}
}
调试显示它命中filterChain.doFilter(request, response)
,然后直接跳转到异常捕获objectMapper
行
提交的用户也是“学生”角色。
2条答案
按热度按时间w8f9ii691#
这 条 线
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(email, null);
缺少 权限 :
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(email, null, authorities);
个wr98u20j2#
希望我的回答能有所帮助,你可以放下一个断点来改变行的响应状态,然后检查是谁以及为什么它返回403,它最终可以帮助你得到解决方案
1.在设置403状态的行上放置一个断点,以从堆栈帧中查看这是如何发生的。
假设它返回403,没有其他信息,但它必须设置响应的状态,对吗?因此,将断点放置到setStatus方法,我不知道它应该位于何处,在tomcat库、spring库或servlet库中。检查HttpResponse,它们是几个实现,为那些setStatus/setCode方法设置断点。(接下来,您可以看到它实际上发生在HttpResponseWrapper::setStatus)
1.分析堆栈帧以查看其中发生了什么
请检查https://stackoverflow.com/a/73577697/4033979