从版本3.2.x升级spring-security到版本4.0.2后,我能够登录到Web应用程序,但是如果它尝试访问具有@PreAuthorized(hasRole)的方法,则会拒绝访问())。
我试图注入' ROLE _'进入GrantAuthorities列表,但结果是一样的。
相同的配置在版本3.2.x中正常工作。谁能知道我做错了什么?
由于
security-context.xml
<http pattern="/css/**" security="none" />
<http pattern="/Images/**" security="none" />
<http pattern="/javascript/**" security="none" />
<http auto-config='true' use-expressions="true" create-session="always"
authentication-manager-ref="tunAuthenticationManager">
<csrf disabled="true" />
<intercept-url pattern="/new/**"
access="hasRole('eu_rw') or hasRole('sp_rw')" />
<intercept-url pattern="/ajax/**"
access="hasRole('eu_rw') or hasRole('sp_rw')" />
<intercept-url pattern="/v2/**"
access="hasRole('eu_rw') or hasRole('sp_rw')" />
<intercept-url pattern="/monitoring" access="hasRole('sp_rw')" />
<intercept-url pattern="/monitoring/**" access="hasRole('sp_rw')" />
<form-login login-page="/logon.jsp" username-parameter="username"
password-parameter="password" login-processing-url="/j_spring_security_check"
authentication-failure-url="/logon.jsp?login_error=1"
default-target-url="/" always-use-default-target="true" />
<custom-filter position="FIRST" ref="logoutFilter" />
<custom-filter after="FIRST" ref="requestLoggingFilter" />
<custom-filter after="LAST" ref="passwordExpirationCheckFilter" />
<custom-filter after="SWITCH_USER_FILTER" ref="authorizationAdjustmentFilter" />
<custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="ajaxTimeoutRedirectFilter" />
</http>
<authentication-manager id="tunAuthenticationManager">
<authentication-provider ref="strongDaoAuthenticationProviderProxy" />
<authentication-provider ref="tunAdAuthenticationProvider" />
</authentication-manager>
<beans:bean id="strongDaoAuthenticationProviderProxy"
class="local.company.tun.security.DaoAuthenticationProviderProxy">
<beans:constructor-arg>
<beans:bean id="strongDaoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="jdbcUserDetailsService" />
<beans:property name="passwordEncoder" ref="strongEncoder" />
<beans:property name="saltSource" ref="saltSource" />
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="jdbcUserDetailsService"
class="local.company.tun.security.tunUserDetailsService">
</beans:bean>
<beans:bean id="authenticationService"
class="local.company.tun.security.service.impl.AuthenticationServiceImpl">
<beans:qualifier value="authenticationService" />
<beans:property name="authenticationManager" ref="tunAuthenticationManager" />
</beans:bean>
<beans:bean
class="local.company.tun.security.DefaultRolesPrefixPostProcessor" />
servlet的context.xml中
<mvc:interceptors>
<!-- Changes the locale when a 'locale' request parameter is sent;
e.g. /?locale=de -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>
<!-- Activate scanning of @Autowired -->
<context:annotation-config />
<!-- Spring Security - enable pre- post- annotations on Spring managed
MVC components -->
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" >
</bean>
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
...
答案 0 :(得分:2)
您必须在角色名称中使用ROLE_
前缀,并在GrantedAuthorities
中使用相同的内容,否则除非您将前缀设置为空,否则它将无效。
RoleVoter.setRolePrefix("");
@PreAuthorize("hasRole('ROLE_ADMIN')")
new SimpleGrantedAuthority("ROLE_ADMIN")
还有一个想法如何调试。在userDetails.getAuthorities()方法中加上一个断点。然后访问受保护的资源。 Spring将检查权限的实际版本并将被捕获。向上浏览堆栈跟踪,找到比较的地点和值,找出问题所在。
答案 1 :(得分:1)
我可以通过添加
来解决此问题<beans:bean
class="local.company.tun.security.DefaultRolesPrefixPostProcessor" />
到security-context.xml和servlet-context.xml。看起来两个地方都需要它。 security-context.xml中的bean将阻止添加&#34; ROLE _&#34;到了 servlet-context.xml中的bean将阻止添加&#34; ROLE _&#34;到了 方法水平。
作为参考,DefaultRolePrefixPostProcessor.java是来自spring security migration 3的复制 - &gt; 4.这里是完整性的源代码。
公共类DefaultRolesPrefixPostProcessor实现BeanPostProcessor,PriorityOrdered {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
Logger logger = LoggerFactory.getLogger(DefaultRolesPrefixPostProcessor.class);
// remove this if you are not using JSR-250
if(bean instanceof Jsr250MethodSecurityMetadataSource) {
((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null);
}
if(bean instanceof DefaultMethodSecurityExpressionHandler) {
logger.info("overriding the default Role prefix. set it to null ");
((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
}
if(bean instanceof DefaultWebSecurityExpressionHandler) {
((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
}
if(bean instanceof SecurityContextHolderAwareRequestFilter) {
((SecurityContextHolderAwareRequestFilter)bean).setRolePrefix("");
}
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public int getOrder() {
return PriorityOrdered.HIGHEST_PRECEDENCE;
}
}
答案 2 :(得分:0)
您可以使用hasAuthority()代替hasRole(),hasAuthority()不会附加defaultRolePrefix。另外,您也可以将其添加到security-context.xml中,以将defaultRolePrefix覆盖为null:
<!-- Remove defaultRolePrefix from SecurityExpressionRoot.java to prevent hasRole() call from appending "ROLE_" to role parameters -->
<bean id="defaultWebSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
<property name="defaultRolePrefix" value=""></property>
</bean>
<bean id="defaultMethodSecurityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="defaultRolePrefix" value=""></property>
</bean>
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="defaultMethodSecurityExpressionHandler" />
</security:global-method-security>