Spring Security 4.1 升级 - 错误 403 访问被拒绝
Posted
技术标签:
【中文标题】Spring Security 4.1 升级 - 错误 403 访问被拒绝【英文标题】:Spring Security 4.1 upgrade - Error 403 Access Denied 【发布时间】:2017-01-10 11:30:50 【问题描述】:我在升级到 Spring Security 4.1.2 和 Spring 4.3.2 时收到 403 Access Denied Error code
Spring-Security.xml 文件
...
<spring:bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter">
</spring:bean>
<spring:bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter"/>
<spring:bean id="webExpressionVoter" class="org.springframework.security.web.access.expression.WebExpressionVoter" />
<spring:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<spring:constructor-arg>
<spring:list>
<spring:ref bean="roleVoter"/>
<spring:ref bean="authenticatedVoter"/>
<spring:ref bean="webExpressionVoter"/>
</spring:list>
</spring:constructor-arg>
</spring:bean>
<security:http access-decision-manager-ref="accessDecisionManager" auto-config='true' use-expressions="true">
<security:intercept-url pattern="/login.jsp" access="hasRole('ROLE_ANONYMOUS')" />
<security:intercept-url pattern="/j_spring_security_check" access="hasRole('ROLE_ANONYMOUS')" />
<security:intercept-url pattern="/index*" access="hasRole('ROLE_USER')"/>
<security:form-login login-page="/login.jsp"
username-parameter="j_username"
password-parameter="j_password"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/accessDenied.jsp" />
<security:logout invalidate-session="true" delete-cookies="JSESSIONID"/>
<security:csrf disabled="true"/>
</security:http>
...
我正在使用 Spring Security AuthenticationProvider 类进行身份验证。类中的authenticate(Authentication authentication)方法执行成功,返回新的UsernamePasswordAuthenticationToken(user, pwd, authority)。
错误堆栈跟踪:
2016-09-02 14:59:21,461 DEBUG [http-/127.0.0.1:8080-1] [org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:66)] - Voter: org.springframework.security.access.vote.RoleVoter@52989292, returned: 0
2016-09-02 14:59:21,461 DEBUG [http-/127.0.0.1:8080-1] [org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:66)] - Voter: org.springframework.security.access.vote.AuthenticatedVoter@203cc7cd, returned: 0
2016-09-02 14:59:21,461 DEBUG [http-/127.0.0.1:8080-1] [org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:66)] - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5e01cc46, returned: -1
2016-09-02 14:59:21,462 DEBUG [http-/127.0.0.1:8080-1] [org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:362)] - Publishing event in Root WebApplicationContext: org.springframework.security.access.event.AuthorizationFailureEvent[source=FilterInvocation: URL: /index.html]
2016-09-02 14:59:21,462 DEBUG [http-/127.0.0.1:8080-1] [org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException(ExceptionTranslationFilter.java:186)] - Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
从错误堆栈跟踪中,WebExpressionVoter 返回 -1。
【问题讨论】:
在 Spring Security 4.1 迁移之前,WebExpressionVoter 没有添加到 AffirmativeBased 决策管理器中。但是,在 4.1 中,似乎必须添加 WebExpressionVoter。而且,这个选民返回 -1。 另外,为什么错误堆栈跟踪的下面一行说“不是匿名的”? - 访问被拒绝(用户不是匿名的) 【参考方案1】:spring安全文件中将hasRole替换为hasAuthority后解决。
【讨论】:
【参考方案2】:如果我们在很多地方都使用hasAnyRole
、hasRole
,那么用hasAuthority
替换所有都是不可行的。这是 Spring 中一个非常令人困惑的升级。如果我们想使用与 Spring 3 相同的角色名称,我们需要附加 ROLE_ 角色名称。例如,如果您使用的是 APP_ADMIN,如果登录用户具有角色 APP_ADMIN,则 Spring 3 将评估 hasRole(APP_ADMIN)
为 true。为了在 Spring 4 中进行同样的操作,您需要将角色更改为 ROLE_APP_ADMIN 以使 hasRole(APP_ADMIN)
为真。
除了制造混乱之外,这根本没有任何意义,无论“创作者”给出的解释是什么
【讨论】:
以上是关于Spring Security 4.1 升级 - 错误 403 访问被拒绝的主要内容,如果未能解决你的问题,请参考以下文章
spring security3.1升级到4.1问题访问/j_spring_security_check 404
Spring Boot 和 Spring Cloud Security OAUTH 2 SSO 在最新版本中失败
Spring Boot /h2-console 使用 Spring Security 1.5.2 抛出 403