spring security oauth2 动态切换角色或者岗位,更新redis缓存

1、切换角色或者岗位后更新缓存token,获取token,并更新token,特别要注意token中的内容

accessToken.getAdditionalInformation().put(SecurityConstants.DETAILS_POST_ID,postId);
 String key = authenticationKeyGenerator.extractKey(originalOAuth2Authentication);
                    byte[] serializedKey =  serializationStrategy.serialize(CacheConstants.PROJECT_OAUTH_ACCESS+"auth_to_access:" + key);
                    byte[] bytes = null;
                    RedisConnection conn = redisConnectionFactory.getConnection();
                    try {
                        bytes = conn.get(serializedKey);
                    } finally {
                        conn.close();
                    }
                    OAuth2AccessToken accessToken =serializationStrategy.deserialize(bytes,OAuth2AccessToken.class);
                    accessToken.getAdditionalInformation().put(SecurityConstants.DETAILS_POST_ID,postId);
                        tokenStore.storeAccessToken(accessToken,oauth2Authentication);

切换用户后,进行数据的更新。

 SysUser user = userService.selectUserByUserName(SecurityUtils.getUser().getUsername());
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        List<SysPost> postList= postService.selectPostsByUserName(user.getUserName());
        user.setPosts(postList);
        user.setPostId(postId);
        //角色集合
        //先查询对应岗位的角色ID
        Set<Integer> roles=postService.selectRoleIdsByPostId(postId);
        if(roles.size()<1){
            return R.failed("该岗位无权访问系统");
        }
        user.setRoleIds(roles.toArray(new Integer[roles.size()]));
        // 角色集合
        //Set<Integer> roles = permissionService.getRolePermission(sysUser.getUserId());
        // 权限集合
        //Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
        Set<String> permissions = permissionService.getMenuPermissionByRoles(user.getUserId(),roles);
        Set<String> dbAuthsSet = new HashSet<>();
        if (ArrayUtil.isNotEmpty(roles)) {
            // 获取角色
            roles.forEach(role -> dbAuthsSet.add(SecurityConstants.ROLE + role));
            // 获取资源
            dbAuthsSet.addAll(permissions);

        }
        Collection<? extends GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(dbAuthsSet.toArray(new String[0]));

//        // 构造security用户
        UserDetails userDetails =new ItduUser(user.getUserId(),postId, user.getDeptId(), user.getRoles(), user.getUserName(),
                SecurityConstants.BCRYPT + user.getPassword(),
                StrUtil.equals("0", CommonConstants.STATUS_NORMAL), true, true, true, authorities);
        Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
        if (cache != null) {
            cache.put(user.getUserName(), userDetails);
        }
        ItduUser itduUser = new ItduUser(user.getUserId(),postId, user.getDeptId(), user.getRoles(), user.getUserName(), N_A, true, true, true, true, authorities);

        //替换oauth认证的信息里的details,这里就不展示了
       if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication originalOAuth2Authentication = (OAuth2Authentication) authentication;
            if (!originalOAuth2Authentication.isClientOnly()) {
                Authentication userAuthentication = originalOAuth2Authentication.getUserAuthentication();
                if (userAuthentication instanceof UsernamePasswordAuthenticationToken) {
                        //替换用户信息,权限信息根据自己的需求替换,这里直接取原来的
                        UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(itduUser, N_A, authorities);
                        usernamePasswordAuthentication.setDetails(itduUser);
                        OAuth2Authentication oauth2Authentication = new OAuth2Authentication(originalOAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);
                        oauth2Authentication.setDetails(itduUser);
                    String key = authenticationKeyGenerator.extractKey(originalOAuth2Authentication);
                    byte[] serializedKey =  serializationStrategy.serialize(CacheConstants.PROJECT_OAUTH_ACCESS+"auth_to_access:" + key);
                    byte[] bytes = null;
                    RedisConnection conn = redisConnectionFactory.getConnection();
                    try {
                        bytes = conn.get(serializedKey);
                    } finally {
                        conn.close();
                    }
                    OAuth2AccessToken accessToken =serializationStrategy.deserialize(bytes,OAuth2AccessToken.class);
                    accessToken.getAdditionalInformation().put(SecurityConstants.DETAILS_POST_ID,postId);
                        tokenStore.storeAccessToken(accessToken,oauth2Authentication);
                }
            }
        }

后期使用

SecurityContextHolder.getContext().getAuthentication()   即可获取到当前登陆用户的相关信息

完整代码:

package com.intasect.upms.sys.controller;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.intasect.common.core.constant.CacheConstants;
import com.intasect.common.core.constant.CommonConstants;
import com.intasect.common.core.constant.SecurityConstants;
import com.intasect.common.core.constant.UserConstants;
import com.intasect.common.core.util.R;
import com.intasect.common.core.util.StringUtils;
import com.intasect.common.security.annotation.Inner;
import com.intasect.common.security.service.ItduUser;
import com.intasect.common.security.util.RedisTokenStore;
import com.intasect.common.security.util.SecurityUtils;
import com.intasect.upms.api.domain.SysPost;
import com.intasect.upms.api.domain.SysUser;
import com.intasect.upms.api.model.LoginUser;
import com.intasect.upms.sys.service.ISysPermissionService;
import com.intasect.upms.sys.service.ISysPostService;
import com.intasect.upms.sys.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;


/**
 * 用户信息
 */
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class SysUserController
{
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private ISysPermissionService permissionService;
    @Autowired
    private   RedisConnectionFactory redisConnectionFactory;
    private AuthenticationKeyGenerator authenticationKeyGenerator=new
            DefaultAuthenticationKeyGenerator();
    private JdkSerializationStrategy serializationStrategy=new JdkSerializationStrategy();
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private  CacheManager cacheManager;

    private static final String N_A = "N/A";

    /**
     * 获取用户列表
     */
    @PreAuthorize("@pms.hasPermission('system:user:list')")
    @GetMapping("/list")
    public R list(Page page, SysUser user)
    {
        return R.ok(userService.selectUserListPage(user,page));
    }

    /**
     * 切换岗位后相关角色和权限的切换
     */
    @GetMapping("/switch/{postId}")
    public R switchPost(@PathVariable("postId") Integer postId, HttpServletRequest request, HttpServletResponse response){
        SysUser user = userService.selectUserByUserName(SecurityUtils.getUser().getUsername());
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        List<SysPost> postList= postService.selectPostsByUserName(user.getUserName());
        user.setPosts(postList);
        user.setPostId(postId);
        //角色集合
        //先查询对应岗位的角色ID
        Set<Integer> roles=postService.selectRoleIdsByPostId(postId);
        if(roles.size()<1){
            return R.failed("该岗位无权访问系统");
        }
        user.setRoleIds(roles.toArray(new Integer[roles.size()]));
        // 角色集合
        //Set<Integer> roles = permissionService.getRolePermission(sysUser.getUserId());
        // 权限集合
        //Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
        Set<String> permissions = permissionService.getMenuPermissionByRoles(user.getUserId(),roles);
        Set<String> dbAuthsSet = new HashSet<>();
        if (ArrayUtil.isNotEmpty(roles)) {
            // 获取角色
            roles.forEach(role -> dbAuthsSet.add(SecurityConstants.ROLE + role));
            // 获取资源
            dbAuthsSet.addAll(permissions);

        }
        Collection<? extends GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(dbAuthsSet.toArray(new String[0]));

//        // 构造security用户
        UserDetails userDetails =new ItduUser(user.getUserId(),postId, user.getDeptId(), user.getRoles(), user.getUserName(),
                SecurityConstants.BCRYPT + user.getPassword(),
                StrUtil.equals("0", CommonConstants.STATUS_NORMAL), true, true, true, authorities);
        Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
        if (cache != null) {
            cache.put(user.getUserName(), userDetails);
        }
        ItduUser itduUser = new ItduUser(user.getUserId(),postId, user.getDeptId(), user.getRoles(), user.getUserName(), N_A, true, true, true, true, authorities);

        //替换oauth认证的信息里的details,这里就不展示了
       if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication originalOAuth2Authentication = (OAuth2Authentication) authentication;
            if (!originalOAuth2Authentication.isClientOnly()) {
                Authentication userAuthentication = originalOAuth2Authentication.getUserAuthentication();
                if (userAuthentication instanceof UsernamePasswordAuthenticationToken) {
                        //替换用户信息,权限信息根据自己的需求替换,这里直接取原来的
                        UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(itduUser, N_A, authorities);
                        usernamePasswordAuthentication.setDetails(itduUser);
                        OAuth2Authentication oauth2Authentication = new OAuth2Authentication(originalOAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);
                        oauth2Authentication.setDetails(itduUser);
                    String key = authenticationKeyGenerator.extractKey(originalOAuth2Authentication);
                    byte[] serializedKey =  serializationStrategy.serialize(CacheConstants.PROJECT_OAUTH_ACCESS+"auth_to_access:" + key);
                    byte[] bytes = null;
                    RedisConnection conn = redisConnectionFactory.getConnection();
                    try {
                        bytes = conn.get(serializedKey);
                    } finally {
                        conn.close();
                    }
                    OAuth2AccessToken accessToken =serializationStrategy.deserialize(bytes,OAuth2AccessToken.class);
                    accessToken.getAdditionalInformation().put(SecurityConstants.DETAILS_POST_ID,postId);
                    tokenStore.storeAccessToken(accessToken,oauth2Authentication);
                }
            }
        }

        return R.ok();
    }


    /**
     * 获取当前用户信息
     */
    @Inner
    @GetMapping("/info/{username}")
    public R<LoginUser> info(@PathVariable("username") String username)
    {
        SysUser sysUser = userService.selectUserByUserName(username);
        if (StringUtils.isNull(sysUser))
        {
            return R.failed("用户名或密码错误");
        }

        //根据业务需求需要根据岗位来查询相关角色及权限
       List<SysPost> postList= postService.selectPostsByUserName(sysUser.getUserName());
        //首次登陆默认使用第一个岗位来登陆,使用岗位获取角色。

        if(postList.size()<1){
            return R.failed("用户暂无所属岗位,无法登陆");
        }

        sysUser.setPosts(postList);
        sysUser.setPostId(postList.get(0).getPostId());
        //角色集合
        //先查询对应岗位的角色ID
        Set<Integer> roles=postService.selectRoleIdsByPostId(postList.get(0).getPostId());
        if (SysUser.isAdmin(sysUser.getUserId()))
        {
            roles.add(1);
        }
        if(roles.size()<1){
            return R.failed("用户暂无所属角色,无法登陆");
        }

        // 角色集合
        //Set<Integer> roles = permissionService.getRolePermission(sysUser.getUserId());
        // 权限集合
        //Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
        Set<String> permissions = permissionService.getMenuPermissionByRoles(sysUser.getUserId(),roles);

        LoginUser sysUserVo = new LoginUser();
        sysUserVo.setSysUser(sysUser);
        sysUserVo.setRoles(roles);
        sysUserVo.setPermissions(permissions);
        return R.ok(sysUserVo);
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public R getInfoByPost(){
//        OAuth2Authentication originalOAuth2Authentication = (OAuth2Authentication)SecurityUtils.getAuthentication();
//        OAuth2AccessToken token = tokenStore.getAccessToken(originalOAuth2Authentication);
//        OAuth2Authentication authentication=tokenStore.readAuthentication(token);
//        ItduUser itduUser=(ItduUser)authentication.getUserAuthentication().getPrincipal();
       // Integer userId = itduUser.getId();
        SysUser sysUser=userService.selectUserById(SecurityUtils.getUser().getId());

        // 角色集合
        //Set<Integer> roles = permissionService.getRolePermission(userId);
        // 权限集合
        //Set<String> permissions = permissionService.getMenuPermission(userId);

        //根据业务需求需要根据岗位来查询相关角色及权限
        List<SysPost> postList= postService.selectPostsByUserName(SecurityUtils.getUser().getUsername());
        if(postList.size()<1){
            return R.failed("用户暂无所属岗位,无法登陆");
        }
        sysUser.setPosts(postList);
        sysUser.setPostId(SecurityUtils.getUser().getPostId());
        SysPost sysPost =  postService.selectPostById(SecurityUtils.getUser().getPostId());

        //角色集合
        //先查询对应岗位的角色ID

        Set<Integer> roles=postService.selectRoleIdsByPostId(sysPost.getPostId());
        if (SysUser.isAdmin(sysUser.getUserId()))
        {
            roles.add(1);
        }
        // 角色集合
        //Set<Integer> roles = permissionService.getRolePermission(sysUser.getUserId());
        // 权限集合
        //Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
        Set<String> permissions = permissionService.getMenuPermissionByRoles(sysUser.getUserId(),roles);
        Map<String,Object> map = new HashMap<>();
        map.put("user", sysUser);
        map.put("roles", roles);
        map.put("permissions", permissions);
        return R.ok(map);
    }

    /**
     * 根据用户编号获取详细信息
     */
    @PreAuthorize("@pms.hasPermission('system:user:query')")
    @GetMapping(value = {"/{userId}",""})
    public R getInfo(@PathVariable(value = "userId", required = false) Integer userId)
    {
        Map<String,Object> map = new HashMap<>();
        //List<SysRole> roles = roleService.selectRoleAll();
        //map.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        map.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId))
        {
            map.put("user", userService.selectUserById(userId));
            map.put("postIds", postService.selectPostListByUserId(userId));
            //map.put("roleIds", roleService.selectRoleListByUserId(userId));
        }
        return R.ok(map);
    }

    /**
     * 新增用户
     */
    @PreAuthorize("@pms.hasPermission('system:user:add')")
    @PostMapping
    public R  add(@Validated @RequestBody SysUser user)
    {
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName())))
        {
            return R.failed("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
        {
            return R.failed("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
        {
            return R.failed("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setCreateBy(SecurityUtils.getUser().getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return R.ok(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@pms.hasPermission('system:user:edit')")
    @PutMapping
    public R edit(@Validated @RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
        {
            return R.failed("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
        {
            return R.failed("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setUpdateBy(SecurityUtils.getUser().getUsername());
        return R.ok(userService.updateUser(user));
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@pms.hasPermission('system:user:remove')")
    @DeleteMapping("/{userIds}")
    public R remove(@PathVariable Integer[] userIds)
    {
        return R.ok(userService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@pms.hasPermission('system:user:edit')")
    @PutMapping("/resetPwd")
    public R resetPwd(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(SecurityUtils.getUser().getUsername());
        return R.ok(userService.resetPwd(user));
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@pms.hasPermission('system:user:edit')")
    @PutMapping("/changeStatus")
    public R changeStatus(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        user.setUpdateBy(SecurityUtils.getUser().getUsername());
        return R.ok(userService.updateUserStatus(user));
    }

    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
        tokenStore.setPrefix(CacheConstants.PROJECT_OAUTH_ACCESS);
        return tokenStore;
    }
}

 

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Spring Security OAuth2中,缓存的处理可以使用Jackson进行序列化。具体实现步骤如下: 1. 添加Jackson依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> ``` 2. 实现序列化器 创建一个自定义的序列化器,继承自`JsonSerializer`: ```java public class OAuth2AccessTokenSerializer extends JsonSerializer<OAuth2AccessToken> { @Override public void serialize(OAuth2AccessToken token, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { gen.writeStartObject(); gen.writeStringField("value", token.getValue()); gen.writeNumberField("expiration", token.getExpiration().getTime()); // 其他字段序列化 gen.writeEndObject(); } } ``` 3. 注册序列化器 在配置类中注册序列化器: ```java @Configuration public class JacksonConfiguration { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(OAuth2AccessToken.class, new OAuth2AccessTokenSerializer()); objectMapper.registerModule(module); return objectMapper; } } ``` 4. 配置缓存缓存配置类中,指定序列化器: ```java @Configuration @EnableCaching public class CacheConfiguration extends CachingConfigurerSupport { @Autowired private ObjectMapper objectMapper; @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(OAuth2AccessToken.class, objectMapper))); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(config) .build(); } } ``` 这样就可以使用Jackson进行缓存的序列化了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值