java Spring安全始终返回HTTP 403

olmpazwi  于 2023-02-07  发布在  Java
关注(0)|答案(8)|浏览(230)

我配置了一个定制的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禁止。
我已经调试并确保过滤器的代码确实被触发了。
有什么问题吗?
EDIT-当将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]
xkrw2x1b

xkrw2x1b1#

我有同样的问题给你,每个请求都被403错误阻止,除了[/]请求。经过大量的时间疯狂,我找到了根本原因,那就是[csrf]。
然后我的安全配置如下所示:

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

此配置表示:仅应授权[删除/**]。
我将[delete]操作标记为:

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

希望能帮到什么人。

wvyml7n5

wvyml7n52#

正如其他人所说,403意味着用户已经登录,但没有查看资源的权限;我将检查以下内容:
1.您的控件具有正确的角色权限@Secured( {"ROLE_myAuthority"} )
1.您实际上授予了正确的权限new SimpleGrantedAuthority("ROLE_myAuthority");

  1. UsernamePasswordAuthenticationToken对象实际授予的权限
    1.过滤器已正确注入
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();
    // ... 
}
rpppsulh

rpppsulh3#

唯一(明显)可能导致403的是用户角色没有设置为ROLE_myAuthority

rlcwz9us

rlcwz9us4#

我知道这是一个很老的问题,但我只是有同样的错误,我没有找到任何解决方案在互联网上.

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

我的WebSecurity配置:

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

pkln4tw65#

得到403而不是401通常意味着您已登录,但不允许(通过权限)查看资源。
调试并确认您正在登录的用户具有该权限(我知道您的代码设置了该权限,但可能您设置了其他错误)。

e5njpo68

e5njpo686#

UsernamePasswordAuthenticationToken扩展了AbstractAuthenticationTokenAbstractAuthenticationToken实现了Authentication
Spring安全性调用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);
  }
}
e4yzc0pl

e4yzc0pl7#

这是一个很老的问题,但万一有人偶然发现这篇文章,一个应用程序也有同样的问题,结果是@ControllerAdvice的问题。
基本上,设置是这样的:

@ControllerAdvice
class MainController {
@PreAuthorize("...")
class AdminController extends MainController {

出于一个奇怪的原因,任何从MainController扩展的控制器都会触发AdminController类的@PreAuthorize,即使这个控制器和AdminController类之间没有关系。
在我的例子中,这是一个简单的修复,因为删除@ControllerAdvice就足够了,但是如果您需要@ControllerAdvice,您可以将注解移动到一个从未用作超类的类中。

umuewwlo

umuewwlo8#

令人困惑的是,如果在SecurityFilterChain中设置了任何限制性授权规则,Spring Security也会为所有未定义的端点返回403而不是404。
因此,如果你输入了错误的测试url或者(像我一样)忘记扫描控制器的基本包,这可能会让你陷入一场徒劳的追逐。
例如,如果我调用一个未定义的端点,它将正确返回404

public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests()
        .anyRequest().permitAll();
    return http.build();
}

对于同一调用,此函数返回403

public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests()
        .requestMatchers(GET, "/health/**").permitAll();
    return http.build();
}

相关问题