我的网络安全配置中包含此代码:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**")
.hasRole("ADMIN")
.and()
.httpBasic().and().csrf().disable();
}
所以我添加了一个用户" ADMIN"在我的数据库中的角色,当我尝试使用此用户登录时,我总是得到403错误,然后我启用了spring for log,我找到了这一行:
2015-10-18 23:13:24.112 DEBUG 4899 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /api/user/login; Attributes: [hasRole('ROLE_ADMIN')]
为什么Spring Security正在寻找" ROLE_ADMIN"相反" ADMIN"?
答案 0 :(得分:17)
Spring安全性默认添加前缀“ ROLE _ ”。
如果要删除或更改此内容,请查看
http://forum.spring.io/forum/spring-projects/security/51066-how-to-change-role-from-interceptor-url
编辑:发现了这个: Spring Security remove RoleVoter prefix答案 1 :(得分:14)
在Spring 4中,hasAuthority()
类中定义了两种方法hasAnyAuthority()
和org.springframework.security.access.expression.SecurityExpressionRoot
。这两种方法仅检查您的自定义角色名称,而不添加ROLE_
前缀。定义如下:
public final boolean hasAuthority(String authority) {
return hasAnyAuthority(authority);
}
public final boolean hasAnyAuthority(String... authorities) {
return hasAnyAuthorityName(null, authorities);
}
private boolean hasAnyAuthorityName(String prefix, String... roles) {
Set<String> roleSet = getAuthoritySet();
for (String role : roles) {
String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
if (roleSet.contains(defaultedRole)) {
return true;
}
}
return false;
}
private static String getRoleWithDefaultPrefix(String defaultRolePrefix, String role) {
if (role == null) {
return role;
}
if (defaultRolePrefix == null || defaultRolePrefix.length() == 0) {
return role;
}
if (role.startsWith(defaultRolePrefix)) {
return role;
}
return defaultRolePrefix + role;
}
使用示例:
<http auto-config="false" use-expressions="true" pattern="/user/**" entry-point-ref="loginUrlAuthenticationEntryPoint"> <!--If we use hasAnyAuthority, we can remove ROLE_ prefix--> <intercept-url pattern="/user/home/yoneticiler" access="hasAnyAuthority('FULL_ADMIN','ADMIN')"/> <intercept-url pattern="/user/home/addUser" access="hasAnyAuthority('FULL_ADMIN','ADMIN')"/> <intercept-url pattern="/user/home/addUserGroup" access="hasAuthority('FULL_ADMIN')"/> <intercept-url pattern="/user/home/deleteUserGroup" access="hasAuthority('FULL_ADMIN')"/> <intercept-url pattern="/user/home/**" access="hasAnyAuthority('FULL_ADMIN','ADMIN','EDITOR','NORMAL')"/> <access-denied-handler error-page="/403"/> <custom-filter position="FORM_LOGIN_FILTER" ref="customUsernamePasswordAuthenticationFilter"/> <logout logout-url="/user/logout" invalidate-session="true" logout-success-url="/user/index?logout"/> <!-- enable csrf protection --> <csrf/> </http> <beans:bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:constructor-arg value="/user"/> </beans:bean>
答案 2 :(得分:3)
由于@olyanren很伤心,你可以在Spring 4中使用hasAuthority()方法而不是hasRole()。我正在添加JavaConfig示例:
@Override
protected void configure(HttpSecurity http) throws Exception {
.authorizeRequests()
.antMatchers("/api/**")
.access("hasAuthority('ADMIN')")
.and()
.httpBasic().and().csrf().disable();
}
答案 3 :(得分:1)
您可以创建一个映射器,以在所有角色的开头添加_ROLE
:
@Bean
public GrantedAuthoritiesMapper authoritiesMapper() {
SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
mapper.setPrefix("ROLE_"); // this line is not required
mapper.setConvertToUpperCase(true); // convert your roles to uppercase
mapper.setDefaultAuthority("USER"); // set a default role
return mapper;
}
您应该将映射器添加到您的提供程序中:
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
// your config ...
provider.setAuthoritiesMapper(authoritiesMapper());
return provider;
}
答案 4 :(得分:0)
_ROLE前缀来标识它是角色。角色具有一组权限,也就是权限,这些权限定义了角色的各种权限。 例如:-EDIT_PROFILE,DELETE_PROFILE
您可以定义角色和权限,如果要定义角色,则必须以“ ROLE_”为前缀
在您的情况下,您正在寻找角色,因此默认情况下,spring security将查找以“ ROLE_”为前缀的字符串。