java spring security oauth2 动态 修改当前登录用户的基础信息以及权限2.0(无需重新登录)

两年前写过一篇动态修改角色和权限当时表述的不是很全面
比如如何修改其他用户权限
修改用户信息没有效果等
再写一篇

如何修改其他用户权限

不管如何改变实际需求就是获取用户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);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security是一个功能强大的安全框架,用于在Java应用程序中实现身份验证和授权。JWT(JSON Web Token)是一种轻量级的身份验证和授权机制,其中包含了验证用户身份的加密信息OAuth 2.0是一种开放标准的授权协议,它允许用户授权第三方应用程序访问受保护的资源。 Spring Security可以与JWT和OAuth 2.0结合使用,以提供更强大的身份验证和授权功能。使用JWT作为身份验证机制,可以在用户登录成功后生成一个JWT令牌,并将其加入到HTTP请求的Header中。服务端可以使用JWT中的信息,如用户名和权限,对请求进行验证,确保用户的身份是有效的。而OAuth 2.0允许用户通过授权服务器颁发的token来访问受保护的资源,Spring Security可以集成OAuth 2.0来实现授权验证的逻辑。 通过使用Spring Security结合JWT和OAuth 2.0,可以轻松实现可伸缩、安全的身份验证和授权机制。开发人员可以使用Spring Security提供的各种功能,如用户认证、角色授权和访问控制,来保护应用程序中的敏感操作和数据。此外,使用JWT和OAuth 2.0,可以实现无状态的API身份验证和授权,提高系统的可扩展性和性能。 总之,Spring Security与JWT和OAuth 2.0的结合为应用程序提供了安全、可靠的身份验证和授权机制。开发人员可以根据具体的需求配置和使用这些功能,以保护应用程序的安全和数据的机密性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值