Java Spring 安全总是返回 HTTP 403
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31746466/
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 always returns HTTP 403
提问by kgautron
I have configured a custom Filter
that grants a spring authority for every URL other than /login
:
我已经配置了一个自定义Filter
,为除以下之外的每个 URL 授予 spring 权限/login
:
public class TokenFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
GrantedAuthority authority = new SimpleGrantedAuthority("myAuthority");
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, token, Arrays.asList(authority));
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
and a spring configuration that protects all requests (but /login
) with that authority :
以及login
使用该权限保护所有请求(但 / )的弹簧配置:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().hasAuthority("myAuthority");
}
}
But every request except /login
gets a HTTP 403
Forbidden.
但是除了/login
HTTP403
禁止之外的每个请求。
I have debugged and made sure the code from the filter is really triggered.
我已经调试并确保过滤器中的代码真的被触发了。
What could be the problem?
可能是什么问题呢?
EDIT - when putting spring security logs in debug I get the following stack trace :
编辑 - 将 spring 安全日志放入调试中时,我得到以下堆栈跟踪:
2015-07-31 14:52:42 [http-nio-8002-exec-2] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Accès refusé
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) ~[spring-security-core-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206) ~[spring-security-core-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) ~[spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) ~[spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.0.6.RELEASE.jar:4.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.0.6.RELEASE.jar:4.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-embed-core-7.0.54.jar:7.0.54]
at com.kgwebapps.tonpronostic.security.TokenFilter.doFilter(TokenFilter.java:55) [classes/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1720) [tomcat-embed-core-7.0.54.jar:7.0.54]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1679) [tomcat-embed-core-7.0.54.jar:7.0.54]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_40]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_40]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-7.0.54.jar:7.0.54]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_40]
回答by Zerkz
Getting a 403 instead of a 401 usually means that you were logged in but you are not permitted (via authority) to see a resource.
获得 403 而不是 401 通常意味着您已登录但您未被允许(通过权限)查看资源。
Debug and confirm that the user you are logging in has that authority (I know your code sets it, but maybe you are setting something else wrong).
调试并确认您登录的用户具有该权限(我知道您的代码设置了它,但也许您设置了其他错误)。
回答by Link
The only (obvious) thing that might result to 403 is the users role is not set to ROLE_myAuthority
.
可能导致 403 的唯一(明显)事情是用户角色未设置为ROLE_myAuthority
。
回答by doannx
I have the same issue to you, every request is blocked by 403 error, except the [/] request. After a lot of time in crazy, I found the root cause, that is the [csrf].
Then my security config is like as following:
我对你有同样的问题,每个请求都被 403 错误阻止,除了 [/] 请求。在疯狂了很多时间之后,我找到了根本原因,那就是 [csrf]。
然后我的安全配置如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/delete/**").authenticated().and().httpBasic().and().csrf().disable();
}
This configuration says that: only [delete/**] should be authorized.
And I mark the [delete] action as following:
这个配置说:只有 [delete/**] 应该被授权。
我将 [delete] 操作标记为如下:
@PreAuthorize("hasRole('ROLE_ADMIN')")
void delete(String id);
Hope to help someone.
希望能帮助某人。
回答by Ithar
As others have said 403 means that user is logged in but doesn't have the right permission to view the resource; I would check the following:
正如其他人所说,403 表示用户已登录但没有查看资源的正确权限;我会检查以下内容:
- Your control has the correct role permission
@Secured( {"ROLE_myAuthority"} )
- You had actually granted the correct permission
new SimpleGrantedAuthority("ROLE_myAuthority");
- Actual granted authority from the UsernamePasswordAuthenticationToken object
Filter is been injected correctly
Authentication auth = new UsernamePasswordAuthenticationToken(username, authentication.getCredentials(), authorities); Collection<? extends GrantedAuthority> auths = auth.getAuthorities();` Iterator authsIterator = auths.iterator(); while (authsIterator.hasNext()) { SimpleGrantedAuthority sga = (SimpleGrantedAuthority) authsIterator.next(); sga.getAuthority(); // ... }
- 您的控件具有正确的角色权限
@Secured( {"ROLE_myAuthority"} )
- 您实际上授予了正确的权限
new SimpleGrantedAuthority("ROLE_myAuthority");
- 来自 UsernamePasswordAuthenticationToken 对象的实际授予权限
过滤器被正确注入
Authentication auth = new UsernamePasswordAuthenticationToken(username, authentication.getCredentials(), authorities); Collection<? extends GrantedAuthority> auths = auth.getAuthorities();` Iterator authsIterator = auths.iterator(); while (authsIterator.hasNext()) { SimpleGrantedAuthority sga = (SimpleGrantedAuthority) authsIterator.next(); sga.getAuthority(); // ... }
回答by Beary
UsernamePasswordAuthenticationToken
extends AbstractAuthenticationToken
, AbstractAuthenticationToken
implements Authentication
.
UsernamePasswordAuthenticationToken
扩展AbstractAuthenticationToken
,AbstractAuthenticationToken
实现Authentication
。
Spring security call Authentication's
method isAuthenticated()
to check whether it should be pass.
Spring 安全调用Authentication's
方法isAuthenticated()
来检查它是否应该通过。
So you should call setAuthenticated
of UsernamePasswordAuthenticationToken
instance and set the argument true
.
所以,你应该调用setAuthenticated
的UsernamePasswordAuthenticationToken
实例并设置参数true
。
Like this:
像这样:
public class TokenFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
GrantedAuthority authority = new SimpleGrantedAuthority("myAuthority");
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, token, Arrays.asList(authority));
auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
回答by robin850
Pretty old question but just in case someone stumble upon this post, an application had the same problem and it turns out to be an issue with @ControllerAdvice
.
很老的问题,但以防万一有人偶然发现这篇文章,一个应用程序有同样的问题,结果是@ControllerAdvice
.
Basically, the setup was like this:
基本上,设置是这样的:
@ControllerAdvice
class MainController {
@PreAuthorize("...")
class AdminController extends MainController {
And for a strange reason, any controller extending from MainController
would trigger the @PreAuthorize
of the AdminController
class even though there were no relationships between this controller and the latter.
而对于一个奇怪的原因,从扩展任何控制器MainController
将触发@PreAuthorize
了的AdminController
,即使有此控制器与后者之间没有关系的类。
In my case, it was an easy fix as removing the @ControllerAdvice
was enough but if you need @ControllerAdvice
, you might move the annotation to a class that is never used as a superclass.
在我的情况下,这是一个简单的解决方法,因为删除@ControllerAdvice
就足够了,但是如果您需要@ControllerAdvice
,您可以将注释移动到一个从未用作超类的类。