Skip to content

I、鉴权规则

wangjie edited this page Dec 25, 2019 · 1 revision

权限数据格式

权限泛指能否操作资源,角色是权限的集合。

安全模型RBAC(Role-Based Access Control 基于角色的权限访问控制),使用用户--角色--资源(URL)的对应关系来表示权限,这个对应关系通常都是持久化保存的。

提供给jsets-shiro-spring-boot-starter的权限数据,为如下格式:

权限数据

使用类RolePermRule封装。

实现ShiroFilteRulesProvider

@Service
public class FilteRulesProviderImpl implements ShiroFilteRulesProvider{
	@Autowired
	private JdbcEnhance jdbcEnhance;
	/**
	 * 加载基于角色/资源的权限验证
	 * RolePermRule包含三个属性(url:资源URL、needRoles:访问需要的角色列表、needPerms:访问需要的权限列表)
	 */
	@Override
	public List<RolePermRule> loadRolePermRules(){
            List<RolePermRule> rolePermRules = this.jdbcEnhance
	            .selector()
                    .SELECT("URL,GROUP_CONCAT(T.ROLE_ID ORDER BY R.URL) NEED_ROLES")
                    .FROM("T_ROLE_RESOURCE T")
	            .JOIN("T_RESOURCE R ON T.RESOURCE_ID = R.ID")
		    .GROUP_BY("R.URL")
		    .entityClass(RolePermRule.class)
		    .list();
		return rolePermRules;
	}
	/**
	 * HMAC数字签名权限验证规则配置
         * 为了展示数据原貌使用了硬编码配置
         * 真实场景中可以通过界面配置,比如做一个"接口管理"功能
	 */
	@Override
	public List<RolePermRule> loadHmacRules() {
		// 删除操作需要通过HMAC数字摘要认证并且具有"role_admin"角色
                RolePermRule hmacRule1 = new RolePermRule();
		hmacRule1.setUrl("/hmac_api/delete");
		hmacRule1.setNeedRoles("role_admin");
		/// 其余操作需要通过HMAC数字摘要认证
		RolePermRule hmacRule2 = new RolePermRule();
		hmacRule2.setUrl("/hmac_api/**");
		List<RolePermRule> hmacRules = Lists.newLinkedList();
		hmacRules.add(hmacRule1);
		hmacRules.add(hmacRule2);
		return hmacRules;
	}
	/**
	 * JWT令牌权限验证规则配置
         * 为了展示数据原貌使用了硬编码配置
         * 真实场景中可以通过界面配置,比如做一个"接口管理"功能
	 */
	@Override
	public List<RolePermRule> loadJwtRules() {
		/// 删除操作需要通过JWT令牌认证并且具有"role_admin"角色
		RolePermRule jwtRule1 = new RolePermRule();
		jwtRule1.setUrl("/jwt_api/delete");
		jwtRule1.setNeedRoles("role_admin");
		/// 其余操作需要通过JWT令牌认证
		RolePermRule jwtRule2 = new RolePermRule();
		jwtRule2.setUrl("/jwt_api/**");
		List<RolePermRule> jwtRules = Lists.newLinkedList();
		jwtRules.add(jwtRule1);
		jwtRules.add(jwtRule2);
                return jwtRules;
	}
	/**
	 * 自定义权限验证规则,如果您熟悉shiro的规则表达式,可自定义规则以便定制更简洁有效的规则
         * 如果你扩展了shiro的Filter,通过这个方法为扩展的Filter指定规则
	 */
	@Override
	public List<CustomRule> loadCustomRules() {
		return null;
	}
}

配置ShiroCustomizer

@Configuration
public class ApplicationConfig{
	// 账号数据提供服务
	@Autowired
	private AccountProviderImpl accountProviderImpl;
	// 自定义的加密实现
	@Autowired
	private MyDESPasswordProvider myDESPasswordProvider;
	// 自定义的验证码实现
	@Autowired
	private MyCaptchaService myCaptchaService;
	// 密码输入错误次数超限处理器
	@Autowired
	private PasswdRetryLimitHandler passwdRetryLimitHandler;
	// 鉴权规则数据提供服务
	@Autowired
	private FilteRulesProviderImpl filteRulesProviderImpl;

	@Bean
	public ShiroCustomizer shiroCustomizer() {
		ShiroCustomizer customizer = new ShiroCustomizer();
		// 设置账号数据提供服务
		customizer.setShiroAccountProvider(accountProviderImpl); 
		// 设置加密实现
		customizer.setPasswordProvider(myDESPasswordProvider);
		// 设置验证码实现
		customizer.setCaptchaProvider(myCaptchaService);
		// 设置密码输入错误次数超限处理器
		customizer.setPasswdRetryLimitListener(passwdRetryLimitHandler);
		// 设置鉴权规则数据提供服务
		customizer.setShiroFilteRulesProvider(filteRulesProviderImpl);
		return customizer;
	}
}

刷新鉴权规则

通过FilteRulesProvider提供的鉴权规则会缓存在系统中,如果修改了角色和资源的关联关系,则需要刷新鉴权规则。如下:

@Service
public class ResourceService {
	/**
	 *  角色-资源绑定
	 */
	@Transactional
	public void roleResBind(String roleId, String resourceIds){
		this.roleResourceMapper.deleteResourceByRole(roleId);
		for(String resourceId:CommonUtil.split(resourceIds)){
			RoleResourceEntity roleResource = new RoleResourceEntity();
			roleResource.setRoleId(roleId);
			roleResource.setResourceId(resourceId);
			this.roleResourceMapper.insert(roleResource);
		}
		// 角色对应的资源改变,要刷新动态过滤规则,以便及时应用更新
		ShiroUtils.reloadFilterRules();
	}
}