我的创作纪念日

机缘

使用CSDN是为了记录自己的学习过程以及记录下自己的学习笔记,相比于自己搭建网站,有一个现成且常用的blog为什么不用呢。


收获

自己的笔记也帮别人解决了问题,感觉有成就感。

自己遇到同样的问题忘了怎么解决也可以方便的查看。


日常

有精力的情况下会去更新博客,有时候没时间就周六周日挤一些时间看看需要记录什么就更新一下


成就

最近写了角色权限方面,springsecurity

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;


    @Autowired
    private MenuService menuService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = userService.findUserByUsername(username);

        if(user==null){
            throw new UsernameNotFoundException("用户名不存在");
        }
        // 根据用户id 查询角色权限信息    用户表  角色表 权限表 多表联查
        List<SimpleGrantedAuthority> authorities = getUserAuthorities(user.getId().longValue());

        return new LoginUser(user.getId().longValue(),user.getName(),user.getPassword(),authorities);
    }


    private List<SimpleGrantedAuthority> getUserAuthorities(Long userId) {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();

        // 获取 用户的角色集合
        // TODO
        Set<String> roles =  roleService.getRolesByUserId(userId);
        if (roles.size() > 0) {
            for (String perm : roles) {
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + perm);
                authorities.add(authority);
            }
        }

        //获取 用户的权限信息
        // TODO
        Set<String> permissions =  menuService.getPermissionsByUserId(userId);

        if (permissions.size() > 0) {
            for (String perm : permissions) {
                if (StringUtils.hasLength(perm)) {
                    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(perm);
                    authorities.add(authority);
                }
            }
        }
        return authorities;
    }
}

token方面操作,jwt

@Service("tokenService")
@Slf4j
@Primary
public class TokenServiceImpl implements TokenService {

    /**
     * token过期秒数
     */
    @Value("${token.expire.seconds}")
    private Integer expireSeconds;

    private static final String LOGIN_USER_KEY = "LOGIN_USER_KEY";


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static Key KEY = null;


    /**
     * 私钥
     */
    @Value("${token.jwtSecret}")
    private String jwtSecret;



    @Override
    public Token saveToken(LoginUser loginUser) {

        // 设置tokenKey
        loginUser.setTokenKey(UUID.randomUUID().toString());

        // 把用户信息存入 redis
        cacheLoginUser(loginUser);

        // 根据 tokenKey s生成token
        String jwtToken = createJWTToken(loginUser);

        return new Token(jwtToken, loginUser.getLoginTime());
    }



    //解析token  获取 redis 中的 key  ,根据 key 获取用户信息

    @Override
    public LoginUser getLoginUser(String jwtToken) {

        //从jwt中获取用户的基本信息
        String uuid = getUUIDFromJWT(jwtToken);

        if (uuid != null) {
            //redis:缓存服务器,暂时存放数据,效率比数据库高的键值对数据库。
            //从redis中获取完整的用户数据
            String s = stringRedisTemplate.boundValueOps(getTokenKey(uuid)).get();
            LoginUser loginUser = JSON.parseObject(s, LoginUser.class);
            return loginUser;
        }
        return null;
    }

    // 删除 token
    @Override
    public boolean deleteToken(String token) {
        String uuid = getUUIDFromJWT(token);
        if (uuid != null) {
            String key = getTokenKey(uuid);
            String loginUser = stringRedisTemplate.opsForValue().get(key);
            if (loginUser != null) {
                stringRedisTemplate.delete(key);
                return true;
            }
        }
        return false;
    }


    //刷新token
    @Override
    public void refresh(LoginUser loginUser) {
        cacheLoginUser(loginUser);
    }


    //解析token
    private String getUUIDFromJWT(String jwtToken) {
        if ("null".equals(jwtToken) || StringUtils.isBlank(jwtToken)) {
            return null;
        }

        try {
            Claims body = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwtToken).getBody();
            return body.get(LOGIN_USER_KEY,String.class);

        } catch (ExpiredJwtException e) {
            log.error("{}已过期", jwtToken);
        } catch (Exception e) {
            log.error("{}", e);
        }

        return null;
    }


    /**
     * 生成jwt
     *
     * @param loginUser
     * @return
     */
    private String createJWTToken(LoginUser loginUser) {

        //自定义准备封装到token 中的数据
        Map<String, Object> claims = new HashMap<>();
        claims.put(LOGIN_USER_KEY, loginUser.getTokenKey());// 放入一个随机字符串,通过该串可找到登陆用户

        String jwtToken = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance())
                .compact();

        return jwtToken;
    }

    private Key getKeyInstance() {
        if (KEY == null) {
            synchronized (TokenServiceImpl.class) {
                if (KEY == null) {// 双重锁
                    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(jwtSecret);
                    KEY = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
                }
            }
        }
        return KEY;
    }

    //把认证之后的数据存入redis
    private void cacheLoginUser(LoginUser loginUser) {

        //设置登陆时间
        loginUser.setLoginTime(System.currentTimeMillis());
        // 设置过期时间
        loginUser.setExpireTime(loginUser.getLoginTime() + expireSeconds * 1000);
        // 根据uuid将loginUser缓存
        //redisTemplate.boundValueOps(getTokenKey(securityUser.getToken())).set(securityUser, expireSeconds, TimeUnit.SECONDS);

        stringRedisTemplate.opsForValue().set(getTokenKey(loginUser.getTokenKey()), JSON.toJSONString(loginUser),expireSeconds, TimeUnit.SECONDS);
    }


    private String getTokenKey(String uuid) {
        return "tokens:" + uuid;
    }



}

憧憬

好好学习,提升自身硬实力

Tips

  1. 您发布的文章将会展示至 里程碑专区 ,您也可以在 专区 内查看其他创作者的纪念日文章
  2. 优质的纪念文章将会获得神秘打赏哦
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值