Spring boot Spring boot authorization使用@RolesAllowed、@Secured或@PreAuthorize返回403来处理任何授权请求

Spring boot Spring boot authorization使用@RolesAllowed、@Secured或@PreAuthorize返回403来处理任何授权请求,spring-boot,jwt,authorization,http-status-code-403,Spring Boot,Jwt,Authorization,Http Status Code 403,我一直在写这篇文章(以及其他一些类似的文章): 客户端是Angular 8应用程序,它从独立的微服务获取Jwt。尝试将筛选器添加到不同的微服务,以通过jwt角色要求特定授权 始终收到403个错误 安全配置: @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true, jsr250Enabled = true) public class WebS

我一直在写这篇文章(以及其他一些类似的文章):

客户端是Angular 8应用程序,它从独立的微服务获取Jwt。尝试将筛选器添加到不同的微服务,以通过jwt角色要求特定授权

始终收到403个错误

安全配置:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true,
        securedEnabled = true,
        jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private BCryptPasswordEncoder bCryptPasswordEncoder;

    public WebSecurityConfig() {}

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors().and().csrf().disable()
                // make sure we use stateless session; session won't be used to store user's state.
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // Add a filter to validate the tokens with every request
                .addFilterAfter(new JwtAuthorizationFilter2(), UsernamePasswordAuthenticationFilter.class)
                // authorization requests config
                .authorizeRequests()
                // Any other request must be authenticated
                .anyRequest().authenticated();
    }
}
过滤器:

public class JwtAuthorizationFilter2 extends OncePerRequestFilter {

    private final String HEADER = "Authorization";
    private final String PREFIX = "Bearer ";
    private final String SECRET = "foo";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String token = request.getHeader(SecurityConstants.HEADER_STRING);
        if (token != null) {
            // parse the token.
            DecodedJWT decoded = JWT.require(Algorithm.HMAC512(SecurityConstants.SECRET.getBytes()))
                    .build()
                    .verify(token.replace(SecurityConstants.TOKEN_PREFIX, ""));

            String user = decoded.getSubject();
            List<SimpleGrantedAuthority> sgas = Arrays.stream(
                    decoded.getClaim("roles").asArray(String.class))
                    .map( s -> new SimpleGrantedAuthority(s))
                    .collect( Collectors.toList());
            if (sgas != null) {
                sgas.add(new SimpleGrantedAuthority("FOO_Admin"));
                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
                        user,
                        null,
                        sgas);
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
            else {
                SecurityContextHolder.clearContext();
            }
            chain.doFilter(request, response);
        }
    }
}
当代码在
SecurityContextHolder.getContext().setAuthentication(auth)
处暂停时,
auth.authenticated=true
auth.authorities
包括一个简单的“FOO_Admin”权限

所以我想知道: FilterChain需要身份验证筛选器(或者身份验证是否发生在JwtAuthorizationFilter2中?)? 角色名称的拼写、格式或大小写没有差异

我被吓呆了。任何帮助都将不胜感激。

希望用户拥有权限
角色\u FOO\u Admin
,其前缀为
角色
。但是,用户只有权限
FOO_Admin
,因此无法访问该方法

您有几个选择:

(1) 通过声明
GrantedAuthorityDefaults
bean来更改前缀:

@Bean
GrantedAuthorityDefaults GrantedAuthorityDefaults(){
返回新的GrantedAuthorityDefaults(“FOO”);
}
并使用
@PreAuthorize(hasRole('Admin'))
保护该方法

(2) 或者更简单的方法是使用
@PreAuthorize(“hasAuthority('FOO_Admin')”)
,它将直接检查用户是否拥有权限
FOO_Admin
,而不向其添加任何前缀


p.S
JwtAuthorizationFilter2
仅验证用户是否有效,并获取相关用户信息,为以后的授权用户做准备。这是一种身份验证,我将其重命名为
JwtAuthenticationFilter2
,以便更准确地描述它的实际功能。

这是我的问题。非常感谢。现在回头看看我是如何错过这次大会的。。。。
.authorizeRequests().antMatchers("/**").hasRole("FOO_Admin")

// or any of these 
@PreAuthorize("hasRole('FOO_Admin')")
@RolesAllowed({"FOO_Admin"})
@Secured({"FOO_Admin"})
Device get(@PathVariable String id) {
    // some code
}