permitAll()需要身份验证

时间:2016-11-07 19:30:02

标签: spring spring-security jwt

我正在使用Spring开发REST应用程序并使用JWT进行身份验证。

目前,我想要实现的目标是:

  • GET /api/subjects/*应该对所有用户都可以访问。
  • POST /api/subjects/*只能由管理员用户访问。

问题是,对于这两种情况,JWT过滤器都会被调用,我得到一个错误响应,说明JWT令牌丢失了。

我已按照以下方式实施了我的WebSecurityConfig,其中包括用于替换BasicAuthenticationFilter的JWT过滤器:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JWTAuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    JWTAuthenticationProvider jwtAuthenticationProvider;

    @Override
    public void configure(WebSecurity web) throws Exception {
        //web.ignoring().antMatchers(HttpMethod.GET,"/api/subjects/*");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/api/subjects/*").permitAll()
                .antMatchers(HttpMethod.POST, "/api/subjects/*").hasRole(Profile.Role.ADMIN.toString())
                .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .addFilterAt(authenticationTokenFilter(), BasicAuthenticationFilter.class)
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
    }

    public JWTAuthenticationFilter authenticationTokenFilter() {
        return new JWTAuthenticationFilter(authenticationManager(), authenticationEntryPoint);
    }

    public ProviderManager authenticationManager() {
        return new ProviderManager(new ArrayList<AuthenticationProvider>(Arrays.asList(jwtAuthenticationProvider)));
    }
}

我对JWTAuthenticationFilter的实施基于BasicAuthenticationFilter

的实施
public class JWTAuthenticationFilter extends OncePerRequestFilter {

    private static final String JWT_TOKEN_START = "JWT ";
    private AuthenticationManager authenticationManager;
    private AuthenticationEntryPoint authenticationEntryPoint;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
        Assert.notNull(authenticationManager, "Authentication Manager must not be null");
        Assert.notNull(authenticationEntryPoint, "Authentication Entry point must not be null");
        this.authenticationManager = authenticationManager;
        this.authenticationEntryPoint = authenticationEntryPoint;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    FilterChain filterChain) throws ServletException, IOException {

        String header = httpServletRequest.getHeader("Authorization");
        if (header == null || !header.startsWith(JWT_TOKEN_START)) {
            throw new IllegalStateException("Header does not contain: \"Authorization\":\"JWT <token>\". Value: "+header);
        }

        try {
            String jwt = header.substring(JWT_TOKEN_START.length()).trim().replace("<", "").replace(">", "");
            JWTAuthenticationToken jwtAuthenticationToken = new JWTAuthenticationToken(jwt);
            this.authenticationManager.authenticate(jwtAuthenticationToken);
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        } catch (AuthenticationException auth) {
            SecurityContextHolder.clearContext();
            this.authenticationEntryPoint.commence(httpServletRequest, httpServletResponse, auth);
        }

    }
}

导致此问题的原因是什么?

0 个答案:

没有答案