我在 Spring Security REST 实现中得到空头值

Posted

技术标签:

【中文标题】我在 Spring Security REST 实现中得到空头值【英文标题】:I am getting null header value in spring security REST implementation 【发布时间】:2018-09-13 14:52:54 【问题描述】:

我正在使用 jersey、spring boot 和 spring security 来创建 rest web 服务。 这将被 Angular 2 客户端使用。

客户端在请求中发送授权标头,但在服务器上我没有收到任何标头值。我正在使用 jersey 作为 web 服务资源,也使用 spring 安全身份验证和授权。

请帮忙。

public class SecurityConfiguration extends WebSecurityConfigurerAdapter

@Autowired
private CustomUserDetailsService userDetailService; 

public SecurityConfiguration(CustomUserDetailsService userDetailService) 
     this.userDetailService  = userDetailService;


@Override
public void configure(WebSecurity web) throws Exception 
    web.ignoring().antMatchers("/assets/**")
    .and().ignoring().antMatchers("/app/**")
    .and().ignoring().antMatchers("/opas/Payment/**") ;


@Override
protected void configure(HttpSecurity http) throws Exception 
    http.csrf().disable();
    http.cors();
    http.authorizeRequests()
            .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
            .antMatchers(HttpMethod.POST, "/login").permitAll()
            .and().authorizeRequests().antMatchers("/opas/common/**").permitAll()
            .and().authorizeRequests().antMatchers("/opas/register/**").permitAll()
            .anyRequest().authenticated()                             
            .and()
            .addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);




@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.userDetailsService(userDetailService);


@Bean
public CorsConfigurationSource corsConfigurationSource() 
    final CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(ImmutableList.of("*"));
    configuration.setAllowedMethods(ImmutableList.of("HEAD","GET", "POST", "PUT", "DELETE", "PATCH","OPTIONS"));
    // setAllowCredentials(true) is important, otherwise:
    // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
    configuration.setAllowCredentials(true);
    // setAllowedHeaders is important! Without it, OPTIONS preflight request
    // will fail with 403 Invalid CORS request
    configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type","X-Requested-With"));
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;

我在下面的代码中得到空头值

public class JWTAuthorizationFilter extends BasicAuthenticationFilter  

public JWTAuthorizationFilter(AuthenticationManager authManager) 
    super(authManager);


@Override
protected void doFilterInternal(HttpServletRequest req,
                                HttpServletResponse res,
                                FilterChain chain) throws IOException, ServletException 
    String header = req.getHeader(HEADER_STRING);

    if (header == null || !header.startsWith(TOKEN_PREFIX)) 
        chain.doFilter(req, res);
        return;
        

    try 
        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
        SecurityContextHolder.getContext().setAuthentication(authentication);       
        chain.doFilter(req, res);
    
    catch (ExpiredJwtException eje) 
        // TODO: handle exception
        ResponseMessage responseMessage = new ResponseMessage();
        responseMessage.setStatusCode(DomainConstants.FORBIDDEN_ERROR);
        responseMessage.setMessage(DomainConstants.SESSION_EXPIRED);
        Gson gson = new Gson();
        res.getWriter().write(gson.toJson(responseMessage));
            


private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request)throws ExpiredJwtException 
    String token = request.getHeader(HEADER_STRING);

        if (token != null) 
            // parse the token.
            String user = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                    .getBody()
                    .getSubject();
            if (user != null)               
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());                  
            
            return null;
                
    return null;

【问题讨论】:

【参考方案1】:

在最新版本的spring中,如果你的header值等于null,你在spring security中得到NullPointerException。也许对于您的情况,您需要使用HttpServletResponseWrapper 将其删除,例如this post

【讨论】:

以上是关于我在 Spring Security REST 实现中得到空头值的主要内容,如果未能解决你的问题,请参考以下文章

REST 服务的基于 Spring Security 的身份验证

使用 REST 和 Javaconfig 在 Spring Security 中摘要 Auth

Spring REST security - 以不同的方式保护不同的 URL

如何使用 Spring Security Oauth 保护 Struts2 Rest 服务

当登录尝试超过 3 次时,用户无法使用 Spring Security Rest API 登录?

使用 Spring Security Rest 插件保护 Grails Rest Api