java Spring Security 匿名 401 而不是 403
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30643029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security anonymous 401 instead of 403
提问by Mati
I have a problem with default behaviour in spring security with authorize requests provided with Java Config.
我在 Spring Security 中的默认行为与 Java Config 提供的授权请求有关。
http
....
.authorizeRequests()
.antMatchers("/api/test/secured/*").authenticated()
When I do a call to for example /api/test/secured/userwithout login (with anonymous user), it returns 403 Forbidden. Is there an easy way to change status to 401 Unauthorized when anonymous user wants to get secured by authenticated()or @PreAuthorizeresource?
例如,当我在/api/test/secured/user没有登录的情况下(使用匿名用户)拨打电话时,它返回 403 Forbidden。当匿名用户想要获得authenticated()或@PreAuthorize资源保护时,是否有一种简单的方法可以将状态更改为 401 Unauthorized ?
采纳答案by Meiblorn
I've got solution here:
我在这里有解决方案:
http
.authenticationEntryPoint(authenticationEntryPoint)
AuthenticationEntryPoint source code:
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");
}
}
回答by le0diaz
With spring security 4.x there is already a class for that
使用 spring security 4.x 已经有一个类
org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint
Spring boot also includes one
Spring Boot 还包括一个
org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
and both benefits that they require the developer to use spec compliant as 401 responses requires that header WWW-Authenticatemust be set, example 401 response could be:
以及他们要求开发人员使用符合规范的两个好处,因为401 响应要求必须设置标头 WWW-Authenticate,例如 401 响应可以是:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
error="invalid_token",
error_description="The access token expired"
So in your security configuration you define and autowire a bean of class
因此,在您的安全配置中,您定义并自动装配了一个类的 bean
So for instance with spring boot app:
因此,例如使用 Spring Boot 应用程序:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
public Http401AuthenticationEntryPoint securityException401EntryPoint(){
return new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"");
}
...
@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(securityException401EntryPoint());
}
the relevant line is:
相关行是:
.exceptionHandling().authenticationEntryPoint(securityException401EntryPoint());
回答by Tai Truong
As of Spring Boot 2 class Http401AuthenticationEntryPoint has been removed (see Spring Boot Issue 10725).
从 Spring Boot 2 开始,Http401AuthenticationEntryPoint 类已被删除(参见Spring Boot 问题 10725)。
Instead of Http401AuthenticationEntryPoint use HttpStatusEntryPoint with HttpStatus.UNAUTHORIZED:
而不是 Http401AuthenticationEntryPoint 使用 HttpStatusEntryPoint 和 HttpStatus.UNAUTHORIZED:
http.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
回答by Sahil Chhabra
You need to extend AuthenticationEntryPointto do customization based upon the exceptions.
您需要扩展AuthenticationEntryPoint以根据异常进行自定义。
@ControllerAdvice
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
// 401
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed");
}
@ExceptionHandler (value = {AccessDeniedException.class})
public void commence(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException {
// 401
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization Failed : " + accessDeniedException.getMessage());
}
}
Specify the above custom AuthenticationEntryPoint in your SecurityConfig like below:
在您的 SecurityConfig 中指定上述自定义 AuthenticationEntryPoint ,如下所示:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity (prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(new MyAuthenticationEntryPoint());
}
}
回答by Hamid Mohayeji
A simple approach in Spring Boot 2 using lambda expressions:
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.\" }");
})
...
}

