簡體   English   中英

Spring 安全總是返回 HTTP 403

[英]Spring security always returns HTTP 403

我已經配置了一個自定義Filter ,它為/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);
      }
}

以及保護具有該權限的所有請求(但 / login )的 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 Forbidden。

我已經調試並確保過濾器中的代碼真的被觸發了。

可能是什么問題呢?

編輯 - 將 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 錯誤阻止,除了 [/] 請求。 在瘋狂了很多時間之后,我找到了根本原因,那就是 [csrf]。
然后我的安全配置如下:

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

這個配置說:只有 [delete/**] 應該被授權。
我將 [delete] 操作標記為如下:

@PreAuthorize("hasRole('ROLE_ADMIN')")
void delete(String id);

希望能幫助某人。

正如其他人所說,403 表示用戶已登錄但沒有查看資源的正確權限; 我會檢查以下內容:

  1. 您的控件具有正確的角色權限@Secured( {"ROLE_myAuthority"} )
  2. 您實際上已授予正確的權限new SimpleGrantedAuthority("ROLE_myAuthority");
  3. 來自 UsernamePasswordAuthenticationToken 對象的實際授予權限
  4. 過濾器被正確注入

    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(); // ... }

可能導致 403 的唯一(明顯)事情是用戶角色未設置為ROLE_myAuthority

獲得 403 而不是 401 通常意味着您已登錄但您未被允許(通過權限)查看資源。

調試並確認您登錄的用戶具有該權限(我知道您的代碼設置了它,但也許您設置了其他錯誤)。

UsernamePasswordAuthenticationToken擴展AbstractAuthenticationTokenAbstractAuthenticationToken實現Authentication

Spring security 調用Authentication's方法isAuthenticated()來檢查是否應該通過

所以你應該調用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
class MainController {
@PreAuthorize("...")
class AdminController extends MainController {

出於一個奇怪的原因,任何從MainController擴展的控制器都會觸發AdminController類的@PreAuthorize ,即使此控制器與后者之間沒有關系。

就我而言,這是一個簡單的修復,因為刪除@ControllerAdvice就足夠了,但是如果您需要@ControllerAdvice ,您可以將注釋移動到一個從未用作超類的類。

我知道這是一個非常古老的問題,但我遇到了同樣的錯誤,而且我沒有在互聯網上找到任何解決方案。
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();

我的網絡安全配置:

public class WebSecurity extends WebSecurityConfigurerAdapter {

...

@Override
    protected void configure(HttpSecurity http) throws Exception {

        http.cors().and().csrf().disable()//
                .authorizeRequests()//
                .antMatchers(...).permitAll()//
                .anyRequest().authenticated()
                .and()
                .sessionManagement()//
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterAfter(authenticationJwtTokenFilter(), BasicAuthenticationFilter.class);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM