可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to remove the "ROLE_" prefix in Spring Security. The first thing I tried was:
http.servletApi().rolePrefix("");
That didn't work, so I tried creating a BeanPostProcessor
as suggested in http://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-jc.html#m3to4-role-prefixing-disable. That didn't work either.
Finally, I tried creating my own SecurityExpressionHandler
:
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .expressionHandler(webExpressionHandler()) .antMatchers("/restricted").fullyAuthenticated() .antMatchers("/foo").hasRole("mycustomrolename") .antMatchers("/**").permitAll(); } private SecurityExpressionHandler webExpressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setDefaultRolePrefix(""); return defaultWebSecurityExpressionHandler; }
However, this doesn't work either. If I use "hasAuthority(roleName)" instead of hasRole
, it works as expected.
Is it possible to remove the ROLE_ prefix from Spring Security's hasRole check?
回答1:
Starting from Spring 4.2, you can define the prefix with a single bean, as described here: https://github.com/spring-projects/spring-security/issues/4134
@Bean GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix }
回答2:
The following configuration works for me.
@Override public void configure(WebSecurity web) throws Exception { web.expressionHandler(new DefaultWebSecurityExpressionHandler() { @Override protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) { WebSecurityExpressionRoot root = (WebSecurityExpressionRoot) super.createSecurityExpressionRoot(authentication, fi); root.setDefaultRolePrefix(""); //remove the prefix ROLE_ return root; } }); }
回答3:
If you are prior to 4.2 and are using so called voters (you are if you use annotations like @hasRole etc) then you need to define below beans in the context:
@Bean public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() { DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler(); defaultMethodSecurityExpressionHandler.setDefaultRolePrefix(""); return defaultMethodSecurityExpressionHandler; } @Bean public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setDefaultRolePrefix(""); return defaultWebSecurityExpressionHandler; }
These beans are used to create evaluation context for spell expressions and they have a defaultRolePrefix set to 'ROLE_'. Although it depends on your use case. This one worked for me and above didn't.
EDIT: answering question about xml configuration -> of course it can be done in xml. Everything done in java config can be written in xml configuration. Here is example (although I did not test it so there might be a typo or something):
回答4:
It appears the new GrantedAuthorityDefaults will change the prefix for the DefaultWebSecurityExpressionHandler and the DefaultMethodSecurityExpressionHandler, but it doesn't modify the RoleVoter.rolePrefix
that is setup from @EnableGlobalMethodSecurity
.
The RoleVoter.rolePrefix is what is used for @Secured("ADMIN")
style of method security.
So along with the GrantedAuthorityDefaults
, I had to also add this CustomGlobalMethodSecurity class to override the defaults for RoleVoter.
@Configuration @EnableGlobalMethodSecurity(securedEnabled = true) public class CustomGlobalMethodSecurity extends GlobalMethodSecurityConfiguration { protected AccessDecisionManager accessDecisionManager() { AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager(); //Remove the ROLE_ prefix from RoleVoter for @Secured and hasRole checks on methods accessDecisionManager.getDecisionVoters().stream() .filter(RoleVoter.class::