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指南