栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security FilterSecurityInterceptor身份验证时如何让Hierarchical Roles生效

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security FilterSecurityInterceptor身份验证时如何让Hierarchical Roles生效

基于spring-security-4.1.0.RELEASE和spring-security-oauth2-2.3.5.RELEASE

如果Spring提供的对外访问的某个接口需要具备某种角色才可以访问时,例如需要具备普通用户(user)角色,你可以配置为如下代码,假设访问的地址为/api/testInterface

@EnableResourceServer
@Configuration
public class ResourceConfig extends ResourceServerConfigurerAdapter {

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				.antMatchers("/api/testInterface").hasRole("user");
	}
}

但你也可能希望管理员(admin)角色能够执行普通用户可以执行的所有操作时,这就牵扯的一个层级角色的问题,也就是Spring Security中提到的Hierarchical Roles,所以这里我们这样配置:

@EnableResourceServer
@Configuration
public class ResourceConfig extends ResourceServerConfigurerAdapter {

	@Bean
	public RoleHierarchy roleHierarchy() {
		RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
		// 该>符号可以被认为是“包括”的意思admin包括user
		roleHierarchy.setHierarchy("ROLE_admin > ROLE_user");
		return roleHierarchy;
	}
	
	public OAuth2WebSecurityexpressionHandler oAuth2WebSecurityexpressionHandler() {
		OAuth2WebSecurityexpressionHandler oAuth2WebSecurityexpressionHandler = new OAuth2WebSecurityexpressionHandler();
		oAuth2WebSecurityexpressionHandler.setRoleHierarchy(roleHierarchy());
		return oAuth2WebSecurityexpressionHandler;
	}

	@Override
	public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
		resources.expressionHandler(oAuth2WebSecurityexpressionHandler());
	}
	
	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				.antMatchers("/api/testInterface").hasRole("user");
	}
}

为啥要设置一个expressionHandler,因为Spring Security中在ResourceServerSecurityConfigurer 中有一个默认的expressionHandler就是OAuth2WebSecurityexpressionHandler,但OAuth2WebSecurityexpressionHandler它的roleHierarchy属性并没有默认的实现,也就是为null,如果我们不手动给它设置,在进行判断认证对象是否包含指定角色时,它只会判断认证对象是否具备user,它不会获取user具备层级角色的关系在进行判断,从而导致通过admin来访问时,被拒绝访问。相关的判断的逻辑大体如下:

public abstract class SecurityexpressionRoot implements SecurityexpressionOperations {
	private String defaultRolePrefix = "ROLE_";
	
	
	
	public final boolean hasRole(String role) {
		return hasAnyRole(role);
	}

	public final boolean hasAnyRole(String... roles) {
		return hasAnyAuthorityName(defaultRolePrefix, roles);
	}
	
	private boolean hasAnyAuthorityName(String prefix, String... roles) {
		Set roleSet = getAuthoritySet();

		for (String role : roles) {
			String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
			if (roleSet.contains(defaultedRole)) {
				return true;
			}
		}

		return false;
	}
	
	
	
	private Set getAuthoritySet() {
		if (roles == null) {
			roles = new HashSet();
			Collection userAuthorities = authentication
					.getAuthorities();

			if (roleHierarchy != null) {
				userAuthorities = roleHierarchy
						.getReachableGrantedAuthorities(userAuthorities);
			}

			roles = AuthorityUtils.authorityListToSet(userAuthorities);
		}

		return roles;
	}
	
	
}

可以看到在getAuthoritySet方法中有一行针对roleHierarchy判断是否为空,如果不为空会把user对应的层级关系添加到roles集合中,这时roles中存在两个角色[ROLE_admin, ROLE_user],这时在通过admin来访问时就没有问题了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/318520.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号