本片主要讲SpringCloud Oauth2篇的实战改造,如动态权限、集成JWT、更改默认url、数据库加载client信息等改造。 同时,这应该也是我这系列博客的完结篇。 关于Oauth2,我也想说几句: 如果真的要应用到企业级项目当中去,必须要进行充足的准备,因为默认的配置、UI等很多都不是通用的(不适用于各个公司), 但是这套框架还好留了很多适配方法等,因此其需要修改的配置、处理器、方法重写等逻辑确实很多很多。 话不多说,正文开始。
1:动态权限
常用的权限校验机制如以下几点:
参考:SpringCloud+SpringSecurity+Oauth2实现角色权限四种方案 - 知乎
类型 | 示例 |
---|---|
硬编码 | 如在接口上添加注解:@PreAuthorize("hasAnyRole('ROLE_ADMIN')") |
HttpSecurity动态增加 | 在资源服务配置类中配置,如:.authorizeRequests().anyRequest().authenticated() |
如果出现用户所拥有的权限出现变化时,上述两种是无法满足的。
百度了几天后网上确实有同学给出了不错的示例,其工作机制如下:
1.1:AccessDecisionManager重写
@Component
public class VipAccessDecisionManager implements AccessDecisionManager {
/**
* 决定当前用户是否有权限访问该请求
**/
@Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
for (ConfigAttribute configAttribute : configAttributes) {
//将访问所需资源或用户拥有资源进行比对
String needAuthority = configAttribute.getAttribute();
if (needAuthority == null) {
continue;
}
for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
if (needAuthority.trim().equals(grantedAuthority.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("抱歉,您没有访问权限");
}
@Override
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
1.2:FilterInvocationSecurityMetadataSource重写
public class VipSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
private Set<PermRoleEntity> permRoleEntitySet;
private final FilterInvocationSecurityMetadataSource superMetadataSource;
private final VipSecurityOauthService vipSecurityOauthService;
public VipSecurityMetadataSource(FilterInvocationSecurityMetadataSource superMetadataSource,
VipSecurityOauthService vipSecurityOauthService) {
this.superMetadataSource = superMetadataSource;
this.vipSecurityOauthService = vipSecurityOauthService;
}
private void loadPerms() {
permRoleEntitySet = vipSecurityOauthService.loadPerms();
}
/**
* 返回能访问该请求的所有角色集合
**/
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
loadPerms();
FilterInvocation fi = (FilterInvocation) object;
String access_uri = fi.getRequestUrl();
for (PermRoleEntity permRoleEntity : permRoleEntitySet) {
if (ANT_PATH_MATCHER.match(permRoleEntity.getAccessUri(), access_uri))
return permRoleEntity.getConfigAttributeList();
}
return superMetadataSource.getAttributes(object);
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
loadPerms();
Set<ConfigAttribute> attributeSet = new HashSet<>();
permRoleEntitySet.stream().map(PermRoleEntity::getConfigAttributeList).forEach(attributeSet::addAll);
return attributeSet;
}
@Over