两年前写过一篇动态修改角色和权限当时表述的不是很全面
比如如何修改其他用户权限
修改用户信息没有效果等
再写一篇
如何修改其他用户权限
不管如何改变实际需求就是获取用户token,不管是当前用户还是所有用户
当前用户的token可以通过上下文拿到,而其他用户的token该如何拿到呢
/**
* 前缀
*/
String BASE_PREFIX = "base_";
/**
* oauth 相关前缀
*/
String OAUTH_PREFIX = "oauth:";
/**
* header 中Authorization
*/
String AUTHORIZATION = "Authorization";
//获取当前请求token
public String getToken() {
try {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
return request.getHeader(CommonConstants.AUTHORIZATION);
} catch (Exception e) {
return "";
}
}
//获取所有的token
private final RedisTemplate<String, Object> redisTemplate;
public Set<String> getToken() {
//获取token的前缀,不清楚的话可以去缓存redis里面找
String key = String.format("%s*", SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX + "auth:*");
ScanOptions build = ScanOptions.scanOptions().match(key).count(10000).build();
return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
Set<String> keysTemp = new HashSet<>();
Cursor<byte[]> cursor = connection.scan(build);
while (cursor.hasNext()) {
keysTemp.add(new String(cursor.next()));
}
return keysTemp;
});
}
经过上述步骤就获取到了token,可以是当前请求的也可以是全部的,之后获取token的存储信息
//获取token存储
private final RedisConnectionFactory redisConnectionFactory;
public RedisTokenStore getRedisTokenStore() {
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
//设置前缀 base_oauth:
tokenStore.setPrefix(SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX);
tokenStore.setAuthenticationKeyGenerator(new DefaultAuthenticationKeyGenerator() {
@Override
public String extractKey(OAuth2Authentication authentication) {
//因为设置了指定前缀
return super.extractKey(authentication) + ":" + TenantContextHolder.getTenantId();
}
});
return tokenStore;
}
拿到token的存储信息就可以通过token获取用户信息了
下面是扩展的user实体类用户信息都是用他存储的
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
/**
* @author 扩展用户信息
*/
@Getter
public class BaseUser extends User {
/**
* 用户ID
*/
private final String id;
private final String nickname;
@Setter
private Set<SysRole> sysRoleSet;
@Setter
private List<SysOrgan> sysOrganList;
/**
* 机构ID
*/
private final String organId;
/**
* 租户ID
*/
private final String tenantId;
public BaseUser(String id, String organId, String tenantId, String nickname, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.id = id;
this.organId = organId;
this.tenantId = tenantId;
this.nickname = nickname;
}
开始拿取用户信息并修改
public void dynamicallyUpdatePermissions() {
//token
Set<String> execute = getToken();
//token存放的地方
RedisTokenStore tokenStore = getRedisTokenStore();
String prefix = SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX + "auth:";
int length = prefix.length();
//将所有token循环
for (String key : execute) {
//拿到token
String token = key.substring(key.indexOf(prefix) + length);
//通过token获取访问令牌
OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(token);
if (oAuth2AccessToken != null) {
//获取Authentication
OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(oAuth2AccessToken);
if (oAuth2Authentication != null) {
//拿取用户信息
Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();
Object principal = userAuthentication.getPrincipal();
//当前BaseUser就是自定义user
if (principal instanceof BaseUser) {
BaseUser baseUser = (BaseUser) principal;
//ps这里能拿到用户信息就可以去修改指定用户的信息
//测试插入用户信息如 新的机构
List<SysOrgan> organList = baseUser.getSysOrganList();
SysOrgan sysOrgan = new SysOrgan();
sysOrgan.setId("8848");
sysOrgan.setName("测试");
organTreeList.add(sysOrgan);
baseUser.setOrganTreeList(organList );
//用户信息存在于OAuth2AccessToken 的AdditionalInformation当中需要修改用户的信息就得修改它
setAdditionalInformation(oAuth2AccessToken, baseUser);
//下面就是修改权限
//添加权限的地方随便测试一下
Set<GrantedAuthority> dbAuthsSet = new HashSet<>(userAuthentication.getAuthorities());
//增加一个权限
dbAuthsSet.add(new SimpleGrantedAuthority("salaryother:warningteam:testroleid"));
UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(baseUser, "N_A", dbAuthsSet);
usernamePasswordAuthentication.setDetails(baseUser);
OAuth2Authentication oauth2Authentication = new OAuth2Authentication(oAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);
oauth2Authentication.setDetails(baseUser);
//更新token
tokenStore.storeAccessToken(oAuth2AccessToken, oauth2Authentication);
}
}
}
}
}
//修改AdditionalInformation ,看着来你有什么属性就加什么属性
String DETAILS_USER_ID = "user_id";
String DETAILS_USERNAME = "username";
String NICK_USERNAME = "nickname";
String ROLE_SET = "sysRoleSet";
String ORGAN_TREE_LIST="sysOrganList";
String DETAILS_ORGAN_ID = "organ_id";
String DETAILS_TENANT_ID = "tenant_id";
String DETAILS_LICENSE = "license";
String BASE_LICENSE = "Copyright © 8848";
private void setAdditionalInformation(OAuth2AccessToken oAuth2AccessToken, BaseUser baseUser) {
final Map<String, Object> additionalInfo = new HashMap<>(12);
additionalInfo.put(SecurityConstants.DETAILS_USER_ID, baseUser.getId());
additionalInfo.put(SecurityConstants.DETAILS_USERNAME, baseUser.getUsername());
additionalInfo.put(SecurityConstants.DETAILS_ORGAN_ID, baseUser.getOrganId());
additionalInfo.put(SecurityConstants.DETAILS_TENANT_ID, baseUser.getTenantId());
additionalInfo.put(SecurityConstants.NICK_USERNAME, baseUser.getNickname());
additionalInfo.put(SecurityConstants.DETAILS_LICENSE, SecurityConstants.BASE_LICENSE);
additionalInfo.put(SecurityConstants.ROLE_SET, baseUser.getSysRoleSet());
additionalInfo.put(SecurityConstants.ORGAN_TREE_LIST, baseUser.getSysOrganList());
((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);
}