具有 spring 安全性的摘要身份验证:按预期收到 401,但有两个 WWW-Authenticate headers
Digest authentication with spring security: 401 recieved as expected but with two WWW-Authenticate headers
当我使用正确的用户名和密码发送 PUT 请求时,它工作正常。
但是当我用错误的密码发送请求时,我收到了 401,这没问题,但是我得到了 2 WWW-Authenticate headers:
响应headers:
HTTP/1.1 401
WWW-Authenticate: 摘要领域="NOKIA.COM", qop="auth", nonce="MTU1MjM3MDk2MDQ2MjpmOWNjYjVmNGU5ODA0ZmY0YWY0MjIxNDlhY2U2ODJiMQ=="
X-Content-Type-Options: nosniff
X-XSS-Protection: 1;模式=块
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
编译指示:no-cache
过期:0
X-Frame-Options:拒绝
WWW-Authenticate: 摘要领域="NOKIA.COM", qop="auth", nonce="MTU1MjM3MDk2MDQ2NjoxOTQ4MDhjNzBjYjkyMGI1Y2Q2YjU3OGMyMTM2NmE3OQ=="
Content-Length: 0
日期:2019 年 3 月 12 日,星期二 06:08:20 GMT
@EnableWebSecurity
@配置
@成分
public class WebSecurityConfig 扩展 WebSecurityConfigurerAdapter
{
@Autowired
DummyUserService userDetail;
@Autowired
DigestAuthenticationFilter digestFilter;
@Autowired
DigestAuthenticationEntryPoint digestEntryPoint;
@Override
protected void configure( HttpSecurity http ) throws Exception
{
http.addFilter(digestFilter) // register digest entry point
.exceptionHandling().authenticationEntryPoint(digestEntryPoint) // on exception ask for digest authentication
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable();
http.httpBasic().disable();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return rawPassword.toString().equals(encodedPassword);
}
};
}
}
@Bean
DigestAuthenticationFilter digestFilter( DigestAuthenticationEntryPoint digestAuthenticationEntryPoint,
UserCache digestUserCache, UserDetailsService userDetailsService )
{
DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
filter.setAuthenticationEntryPoint( digestAuthenticationEntryPoint );
filter.setUserDetailsService( userDetailsService );
filter.setUserCache( digestUserCache );
return filter;
}
@Bean
UserCache digestUserCache() throws Exception
{
return new SpringCacheBasedUserCache( new ConcurrentMapCache( "digestUserCache" ) );
}
@Bean
DigestAuthenticationEntryPoint digestAuthenticationEntry()
{
DigestAuthenticationEntryPoint digestAuthenticationEntry = new DigestAuthenticationEntryPoint();
digestAuthenticationEntry.setRealmName( "XXX.COM" );
digestAuthenticationEntry.setKey( "XXX" );
digestAuthenticationEntry.setNonceValiditySeconds( 60 );
return digestAuthenticationEntry;
}
请有人能给我一些帮助。非常感谢!
我自己解决了这个问题。对于身份验证不正确的请求,DigestAuthenticationEntryPoint 被 digestFilter 和 exceptionFilter 调用了两次。
覆盖 DigestAuthenticationEntryPoint:
public class CustomDigestAuthenticationEntryPoint extends DigestAuthenticationEntryPoint
{
@Override
public void commence( HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException )
throws IOException, ServletException
{
HttpServletResponse httpResponse = ( HttpServletResponse ) response;
String authHeader = httpResponse.getHeader( "WWW-Authenticate" );
if( authHeader != null )
{
httpResponse.sendError( HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase() );
}
else
{
super.commence( request, httpResponse, authException );
}
}
}
当我使用正确的用户名和密码发送 PUT 请求时,它工作正常。 但是当我用错误的密码发送请求时,我收到了 401,这没问题,但是我得到了 2 WWW-Authenticate headers:
响应headers: HTTP/1.1 401
WWW-Authenticate: 摘要领域="NOKIA.COM", qop="auth", nonce="MTU1MjM3MDk2MDQ2MjpmOWNjYjVmNGU5ODA0ZmY0YWY0MjIxNDlhY2U2ODJiMQ=="
X-Content-Type-Options: nosniff X-XSS-Protection: 1;模式=块 Cache-Control: no-cache, no-store, max-age=0, must-revalidate 编译指示:no-cache 过期:0 X-Frame-Options:拒绝
WWW-Authenticate: 摘要领域="NOKIA.COM", qop="auth", nonce="MTU1MjM3MDk2MDQ2NjoxOTQ4MDhjNzBjYjkyMGI1Y2Q2YjU3OGMyMTM2NmE3OQ=="
Content-Length: 0 日期:2019 年 3 月 12 日,星期二 06:08:20 GMT
@EnableWebSecurity
@配置 @成分 public class WebSecurityConfig 扩展 WebSecurityConfigurerAdapter {
@Autowired
DummyUserService userDetail;
@Autowired
DigestAuthenticationFilter digestFilter;
@Autowired
DigestAuthenticationEntryPoint digestEntryPoint;
@Override
protected void configure( HttpSecurity http ) throws Exception
{
http.addFilter(digestFilter) // register digest entry point
.exceptionHandling().authenticationEntryPoint(digestEntryPoint) // on exception ask for digest authentication
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable();
http.httpBasic().disable();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return rawPassword.toString().equals(encodedPassword);
}
};
}
}
@Bean
DigestAuthenticationFilter digestFilter( DigestAuthenticationEntryPoint digestAuthenticationEntryPoint,
UserCache digestUserCache, UserDetailsService userDetailsService )
{
DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
filter.setAuthenticationEntryPoint( digestAuthenticationEntryPoint );
filter.setUserDetailsService( userDetailsService );
filter.setUserCache( digestUserCache );
return filter;
}
@Bean
UserCache digestUserCache() throws Exception
{
return new SpringCacheBasedUserCache( new ConcurrentMapCache( "digestUserCache" ) );
}
@Bean
DigestAuthenticationEntryPoint digestAuthenticationEntry()
{
DigestAuthenticationEntryPoint digestAuthenticationEntry = new DigestAuthenticationEntryPoint();
digestAuthenticationEntry.setRealmName( "XXX.COM" );
digestAuthenticationEntry.setKey( "XXX" );
digestAuthenticationEntry.setNonceValiditySeconds( 60 );
return digestAuthenticationEntry;
}
请有人能给我一些帮助。非常感谢!
我自己解决了这个问题。对于身份验证不正确的请求,DigestAuthenticationEntryPoint 被 digestFilter 和 exceptionFilter 调用了两次。
覆盖 DigestAuthenticationEntryPoint:
public class CustomDigestAuthenticationEntryPoint extends DigestAuthenticationEntryPoint
{
@Override
public void commence( HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException )
throws IOException, ServletException
{
HttpServletResponse httpResponse = ( HttpServletResponse ) response;
String authHeader = httpResponse.getHeader( "WWW-Authenticate" );
if( authHeader != null )
{
httpResponse.sendError( HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase() );
}
else
{
super.commence( request, httpResponse, authException );
}
}
}