我遇到了Spring安全性中的默认行为问题,其中包含Java Config提供的授权请求。
http
....
.authorizeRequests()
.antMatchers("/api/test/secured/*").authenticated()
当我在没有登录(使用匿名用户)的情况下调用例如/api/test/secured/user
时,它返回403 Forbidden。当匿名用户想要通过authenticated()
或@PreAuthorize
资源获得安全保护时,是否有一种简单的方法可以将状态更改为401 Unauthorized?
答案 0 :(得分:15)
使用spring security 4.x已经有了一个类
org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint
Spring boot还包括一个
org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
并且必须设置他们要求开发人员使用符合规范401 responses requires that header WWW-Authenticate的两个好处,例如401响应可能是:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
error="invalid_token",
error_description="The access token expired"
因此,在安全配置中,您可以定义并自动装配类
的bean所以例如使用spring boot app:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
public Http401AuthenticationEntryPoint securityException401EntryPoint(){
return new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"");
}
@Autowired
private Http401AuthenticationEntryPoint authEntrypoint;
...
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").anonymous()
.antMatchers("/").anonymous()
.antMatchers("/api/**").authenticated()
.and()
.csrf()
.disable()
.headers()
.frameOptions().disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.logout()
.permitAll()
.exceptionHandling().authenticationEntryPoint(authEntrypoint);
}
相关的一行是:
.exceptionHandling().authenticationEntryPoint(authEntrypoint);
答案 1 :(得分:10)
我有解决方案here:
http
.authenticationEntryPoint(authenticationEntryPoint)
AuthenticationEntryPoint源代码:
@Component
public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint {
private final Logger log = LoggerFactory.getLogger(Http401UnauthorizedEntryPoint.class);
/**
* Always returns a 401 error code to the client.
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) throws IOException,
ServletException {
log.debug("Pre-authenticated entry point called. Rejecting access");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied");
}
}
答案 2 :(得分:7)
从Spring Boot 2开始,类Http401AuthenticationEntryPoint已被删除(请参阅Spring Boot Issue 10725)。
使用HttpStatusEntryPoint而不是Http401AuthenticationEntryPoint和HttpStatus.UNAUTHORIZED:
http.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
答案 3 :(得分:0)
Spring Boot 2中使用lambda表达式的一种简单方法:
@Override
public void configure(HttpSecurity http) throws Exception {
http.
...
.exceptionHandling()
.authenticationEntryPoint((request, response, e) -> {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json");
response.getWriter().write("{ \"error\": \"You are not authenticated.\" }");
})
...
}
答案 4 :(得分:0)
谁对工作机制感兴趣。
如果你不设置 http.exceptionHandling().authenticationEntryPoint()
spring 将使用 defaultAuthenticationEntryPoint()
而方法 ExceptionHandlingConfigurer.createDefaultEntryPoint()
将返回 new Http403ForbiddenEntryPoint()
因此,只需创建 Http401UnauthorizedEntryPoint()
。上面回答了怎么做,没有重复。
附言实际适用于 Spring Security 5.2.5.RELEASE