Java Spring安全性始终返回HTTP 403

Java Spring安全性始终返回HTTP 403,java,spring,spring-security,Java,Spring,Spring Security,我已经配置了一个自定义的过滤器,它为除/login之外的每个URL授予spring权限: public class TokenFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { GrantedAut

我已经配置了一个自定义的
过滤器
,它为除
/login
之外的每个URL授予spring权限:

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);
      }
}
以及一个spring配置,该配置使用该权限保护所有请求(但/
登录
):

@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");
    }

}
但是除了
/login
之外的每个请求都会得到一个HTTP
403
禁止

我已经调试并确保过滤器中的代码被真正触发

有什么问题吗

编辑-将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]

获得403而不是401通常意味着您已登录,但不允许(通过授权)查看资源


调试并确认您登录的用户具有该权限(我知道您的代码设置了该权限,但可能您设置了其他错误)。

可能导致403的唯一(明显)结果是用户角色未设置为
角色\u我的权限

我对您有相同的问题,每个请求都被403错误阻止,除了[/]请求。经过一段时间的疯狂,我找到了根本原因,那就是[csrf]。
那么我的安全配置如下所示:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/delete/**").authenticated().and().httpBasic().and().csrf().disable();
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
void delete(String id);
此配置说明:只有[delete/**]应该被授权。
我将[删除]操作标记如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/delete/**").authenticated().and().httpBasic().and().csrf().disable();
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
void delete(String id);

希望能帮助他人。

正如其他人所说,403表示用户已登录,但没有查看资源的正确权限;我想检查一下:

  • 您的控件具有正确的角色权限
    @Secured({“ROLE\u myAuthority”})
  • 您实际上已经授予了正确的权限
    新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();
        // ... 
    }
    
    Authentication auth=new UsernamePasswordAuthenticationToken(username,Authentication.getCredentials(),authorities);
    
    集合
    用户名密码身份验证令牌
    扩展
    抽象身份验证令牌
    抽象身份验证令牌
    实现
    身份验证

    因此,您应该调用
    UsernamePasswordAuthenticationToken
    实例的
    setAuthenticated
    ,并设置参数
    true

    像这样:

    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);
      }
    }
    

    这是一个很老的问题,但万一有人无意中发现了这篇文章,一个应用程序也有同样的问题,结果证明这是
    @ControllerAdvice
    的问题

    基本上,设置是这样的:

    @ControllerAdvice
    类主控制器{
    
    @预授权(“…”)
    类AdminController扩展了MainController{
    
    出于奇怪的原因,从
    MainController
    扩展的任何控制器都会触发
    AdminController
    类的
    @预授权
    ,即使该控制器与后者之间没有关系


    在我的例子中,这是一个简单的修复方法,因为删除
    @ControllerAdvice
    就足够了,但是如果您需要
    @ControllerAdvice
    ,您可以将注释移动到一个从未用作超类的类。

    我知道这是一个非常古老的问题,但我只是遇到了同样的错误,并且在internet上没有找到任何解决方案。
    正确的说法是,403表示用户已通过身份验证,但未授权获取资源。这与JWT中的索赔部分有关。
    您的JWT构建器需要为用户设置适当的声明

    List<GrantedAuthority> grantedAuthorities = AuthorityUtils
                    .commaSeparatedStringToAuthorityList("ROLE_USER");
    
    Jwts.builder()//
                    .setIssuer(...)//
                    .setSubject(...)//
                    .setAudience(...)
    
                    // This is the part that you missed
    
                    .claim("authorities",
                            grantedAuthorities.stream()
                            .map(GrantedAuthority::getAuthority)
                            .collect(Collectors.toList()))
    
                    // Ends here
    
                    .setIssuedAt(date)//
                    .setExpiration(new Date(date.getTime() + jwtExpirationMs))
                    .signWith(SignatureAlgorithm.HS512, signingKey)//
                    .compact();
    

    您可以放置一些stacktrace吗?谢谢。您已经声明了一个自定义筛选器,但尚未将其添加到您的配置
    http.addFilter(new-TokenFilter())中,没有任何异常
    。也请查看或感谢Roman Vottner,它成功了!但在此之前,它已被声明为@组件并有效执行。它是否因为过滤器顺序而不起作用?或者“http.addFilter”是否做了一些特殊的事情,而不仅仅是注册过滤器?我根本不知道过滤器是自动发现的。基于Java之前的web配置您需要通过
    customFiltercom.yourcompany.CustomFilter
    以XML形式声明筛选器,但我可以在哪里检查它?执行该操作的代码在spring security中的某个地方,我对框架的理解不够透彻,不知道在哪里可以查看。在调试器上,使用“单步执行”而不是“单步执行”。我认为您可以在相同的配置中添加角色:authorizeRequests().antMatchers(“/delete/**”)。hasRole(“role_ADMIN”)禁用csrf安全吗?@user666简单回答:不安全。但是,当您的网站不允许用户修改任何数据时(在数据库中保存/更新其数据等)然后它就可以安全了(基本上当你只允许GET请求时),因为
    csrf
    保护的目的是防止恶意网站代表用户进行请求。我已经在DB中将我的角色名从user改为role\u user,它可以工作。谢谢@Linkit也可以为我工作,DB中的role\u user和java代码中的user都可以作为角色