java Spring Security @Secured 注解和用户权限
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36711538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security @Secured annotation and User authorities
提问by Andremoniy
This is about Spring
v.4 (MVC + Security). I have implemented UserDetailsServiceImpl
, where inside loadUserByUsername
method user is granted with its authorities. Say it's simply:
这大约是Spring
v.4(MVC + 安全性)。我已经实现了UserDetailsServiceImpl
,其中内部loadUserByUsername
方法用户被授予其权限。简单说一下:
public UserDetails loadUserByUsername(String username) {
...
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ADMIN"));
return new org.springframework.security.core.userdetails.User(username, password, enabled, true, true, true, authorities);
...
}
And I have security controller inside which I've annotated method with @Secured
annotation:
我有一个安全控制器,我在其中用@Secured
注释注释了方法:
@Secured("ADMIN")
@RequestMapping(value = "/users", method = RequestMethod.GET)
public String users(Model model ...) { ... }
As you can see inside loadUserByUsername
I explicitly grant ADMIN
role to user.
But when I'm trying access to /users
I get Access is denied
exception:
正如你在里面看到的,loadUserByUsername
我明确地ADMIN
向用户授予角色。但是,当我试图进入/users
我得到Access is denied
异常:
2016-04-19 10:25:16,899 DEBUG (http-nio-8080-exec-9) [org.springframework.security.web.access.ExceptionTranslationFilter] - Access is denied (user is not anonymous); delegating to AccessDeniedHandler org.springframework.security.access.AccessDeniedException: Access is denied at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70) at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:88) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232) at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:64) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ...
2016-04-19 10:25:16,899 DEBUG (http-nio-8080-exec-9) [org.springframework.security.web.access.ExceptionTranslationFilter] - 访问被拒绝(用户不是匿名的);委派给 AccessDeniedHandler org.springframework.security.access.AccessDeniedException:访问被拒绝在 org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70) 在 org.springframework.security.access.vote.Affirm决定(AffirmativeBased.java:88)在 org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232)在 org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java: 64) 在 org.springframework.aop.framework。
(without @Secured
annotation everything works fine).
(没有@Secured
注释一切正常)。
So, what have I missed here?
那么,我在这里错过了什么?
回答by Andremoniy
Surprisingly, but the problem was with roles names. Due to defaultRolePrefix
set to ROLE_
(see org.springframework.security.access.vote.RoleVoter
class) all roles should have names starting with ROLE_
prefix. In other words, when I've changed
令人惊讶的是,问题出在角色名称上。由于defaultRolePrefix
设置为ROLE_
(参见org.springframework.security.access.vote.RoleVoter
类),所有角色的名称都应以ROLE_
前缀开头。换句话说,当我改变了
authorities.add(new SimpleGrantedAuthority("ADMIN"));
to
authorities.add(new SimpleGrantedAuthority("ADMIN"));
到
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
and @Secured("ADMIN")
to @Secured("ROLE_ADMIN")
- everything became fine.
并@Secured("ADMIN")
以@Secured("ROLE_ADMIN")
-一切都变得很好。
回答by cassiomolin
I also faced this issue. Spring Security 4 automatically prefixes any role with ROLE_
. Refer to the Spring Security 3.x to 4.x migration guidefor more details.
我也遇到过这个问题。Spring Security 4 自动为任何角色添加前缀ROLE_
。有关更多详细信息,请参阅Spring Security 3.x 到 4.x 迁移指南。
Disabling ROLE_
prefixing
禁用ROLE_
前缀
As suggested in the migration guide, the following BeanPostProcessor
can be used to disable the automatic ROLE_
prefixing:
正如迁移指南中所建议的,以下内容BeanPostProcessor
可用于禁用自动ROLE_
前缀:
public class DefaultRolesPrefixPostProcessor implements BeanPostProcessor,
PriorityOrdered {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
// Remove this if you are not using JSR-250
if (bean instanceof Jsr250MethodSecurityMetadataSource) {
((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null);
}
if (bean instanceof DefaultMethodSecurityExpressionHandler) {
((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;
}
}
Then define it as a bean:
然后将其定义为bean:
@Bean
public static DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() {
return new DefaultRolesPrefixPostProcessor();
}
Checking authorities
检查机关
Alternatively you can check the authorities using the @PreAuthorize
annotation:
或者,您可以使用@PreAuthorize
注释检查权限:
@PreAuthorize("hasAuthority('ADMIN')")
Ensure that prePostEnabled
is enabled:
确保prePostEnabled
已启用:
@EnableGlobalMethodSecurity(prePostEnabled = true)