Spring boot 2.0 HttpSecurity auth 在没有发送 Authorization 标头的情况下不起作用

Posted

技术标签:

【中文标题】Spring boot 2.0 HttpSecurity auth 在没有发送 Authorization 标头的情况下不起作用【英文标题】:Spring boot 2.0 HttpSecurity auth doesn't work without sent Authorization header 【发布时间】:2018-11-18 07:59:03 【问题描述】:

我在班级WebSecurity extends WebSecurityConfigurerAdapter 中有此安全设置:

@Override
protected void configure(HttpSecurity http) throws Exception

    http
        .addFilterBefore(corsFilter(), SessionManagementFilter.class)
        .csrf().disable().authorizeRequests()
        .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
        .anyRequest().authenticated()
        .and()
        .addFilter(new JWTAuthenticationFilter(authenticationManager()))
        .addFilter(new JWTAuthorizationFilter(authenticationManager()));

JWTAuthenticationFilter:

class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter

    private AuthenticationManager authenticationManager;
    private Logger                logger = Logger.getLogger("JWTAuthenticationFilter");

    JWTAuthenticationFilter(AuthenticationManager authenticationManager)
    
        this.authenticationManager = authenticationManager;
    

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
    throws AuthenticationException
    
        String username = req.getParameter("username");
        logger.info("Login attempt with username: " + username);

        return authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(username, req.getParameter("password"), new ArrayList<>())
        );
    

    @Override
    protected void successfulAuthentication(
        HttpServletRequest req,
        HttpServletResponse res,
        FilterChain chain,
        Authentication auth
    )
    
        String token = Jwts
            .builder()
            .setSubject(((User) auth.getPrincipal()).getUsername())
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .signWith(SignatureAlgorithm.HS512, SECRET)
            .compact();

        res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
    

JWTAuthorizationFilter:

public class JWTAuthorizationFilter extends BasicAuthenticationFilter

    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;
        
        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request)
    
        String token = request.getHeader(HEADER_STRING);
        if (token != null)
        
            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;
    

当我发送 Authorization: Bearer “正确令牌”标头时,它工作正常。 当我发送 Authorization: Bearer "expired token" 标头时,我收到了正确的错误消息。 但如果我不发送标头,它不会阻塞 API 调用,并且我得到的响应没有错误消息。 如果我发送带有随机文本而不是 Bearer 的 Auth 标头,我会收到没有错误消息的响应。

这有什么问题?

【问题讨论】:

JWTAuthenticationFilter 是如何实现的。 我用代码更新了问题。 我没有看到任何与使用令牌进行身份验证相关的内容。那么它怎么能起作用呢?您基本上是使用用户名和密码登录,然后提供令牌。您无处读取此过滤器中的令牌?那么您的令牌在哪里被读取并用于身份验证? 再次使用 JWTAuthorizationFilter 类更新,问题可能出在此处。 如果我不发送 Authorization 标头,getAuthentication 将不会被触发。 【参考方案1】:

不是专家,但您可以尝试使用

在特定位置添加过滤器
.addFilterBefore(new JWTAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);

如果有变化请告诉我

【讨论】:

JWTAuthenticationFilter 没有第二个参数,加不了。 第二个参数是用于 addFilter 之前,可能是我搞砸了括号 是的,抱歉,我没看到。但是还是不行,我得到了api响应,没有任何错误。

以上是关于Spring boot 2.0 HttpSecurity auth 在没有发送 Authorization 标头的情况下不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2.0:重磅Spring Boot 2.0权威发布

Spring Boot 2.0(一):Spring Boot 2.0尝鲜-动态 Banner

Spring Boot 2.0干货系列:Spring Boot1.5X升级到2.0指南

spring boot 2.0之使用spring boot

Spring Boot 2:Spring Boot 2.0新特性

Spring Boot 2.0:使用 Docker 部署 Spring Boot