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


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

    如何修改其他用户权限

    不管如何改变实际需求就是获取用户token,不管是当前用户还是所有用户
    当前用户的token可以通过上下文拿到,而其他用户的token该如何拿到呢

    /**
     * 前缀
     */
    String BASE_PREFIX = "base_";
    
    /**
     * oauth 相关前缀
     */
    String OAUTH_PREFIX = "oauth:";
    /**
     * header 中Authorization
     */
    String AUTHORIZATION = "Authorization";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //获取当前请求token
    public String getToken() {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            return request.getHeader(CommonConstants.AUTHORIZATION);
        } catch (Exception e) {
            return "";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    //获取所有的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;
        });
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    经过上述步骤就获取到了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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    拿到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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    开始拿取用户信息并修改

    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);
                        }
                    }
    
                }
            }
    
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    //修改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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    数据结构-堆排序
    Python自动导入缺失的库
    图上简单路径问题——转化为圆方树问题:abc318_g
    ESP8266-Arduino编程实例-土壤湿度传感器驱动
    【vue3】13.跟着官网学习vue3-模版引用,provide/inject,父子组件相互调用方法,defineExpose
    全网 灰色主题实现原理
    睿趣科技:抖音店铺怎么取名受欢迎
    初探基因组组装——生信原理第四次实验报告
    出租屋智能视频监控系统方案:全面保卫租客安全
    饿了么三面:让你怀疑人生的Spring Boot夺命连环40问
  • 原文地址:https://blog.csdn.net/ycg_x_y/article/details/137970599