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/user
without 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 @PreAuthorize
resource?
例如,当我在/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 AuthenticationEntryPoint
to 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.\" }");
})
...
}