Spring boot集成token_通过token解析用户信息

Spring boot集成token,接口对token进行校验,并使用token获取登录用户信息

1、缓存token、验证token信息

 /**
     *  缓存token
     * @param userId
     * @param token
     */
    public void setTokenUser(String userId, String token) {
        // 缓存token
        /** token失效时间 18000 = 5小时 7200 = 2小时  3600 = 1小时 1800 = 半小时 900 = 15分钟 60 = 1分钟*/
        MapCache.single().set("tokenUser" + userId, token, 18000); // 两小时过期
        MapCache.single().set(token, getSysUser(), 18000); // 两小时过期
    }

    /**
     * 验证token信息
     *
     * @return User
     */
    public SysUser analyticalUser() {
        String token = null;
        try {
            token = getRequest().getHeader("accessToken");
        } catch (NoSuchMessageException e) {
            /** token失效状态 */
            throw new UserTokenInvalidException("10000", null, "无认证信息,请先登录");
        }
        if (token == null) {
            /** token失效状态 */
            throw new UserTokenInvalidException("10000", null, "无认证信息,请先登录");
        }
        SysUser user = MapCache.single().get(token);
        if (user == null) {
            /** token失效状态 */
            throw new UserTokenInvalidException("10000", null, "认证失效,请先登录");
        }
        /**
         * token缓存常量
         */
        String tokenVerify = MapCache.single().get("tokenUser" + user.getUserId());
        System.out.println(tokenVerify);
        if (!tokenVerify.equals(token)) {
            /** token失效状态 */
            throw new UserTokenInvalidException("10000", null, "登录失效,请先登录");
        }
        MapCache.single().set("tokenUser" + user.getUserId(), token, 18000); // 两小时过期
        MapCache.single().set(token, user, 18000);
        return user;
    }

2、SysUser实体类

/**
 * 用户对象 sys_user
 */
public class SysUser extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 用户ID */
    @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
    private Long userId;

    /** 部门ID */
    @Excel(name = "部门编号", type = Type.IMPORT)
    private Long deptId;

    /** 角色ID */
    private Long roleId;

    /** 登录名称 */
    @Excel(name = "登录名称")
    private String loginName;

    /** 用户名称 */
    @Excel(name = "用户名称")
    private String userName;

    /** 密码 */
    private String password;

    /** 盐加密 */
    private String salt;

    /** 帐号状态(0正常 1停用) */
    @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
    private String status;

    /** 删除标志(0代表存在 2代表删除) */
    private String delFlag;

    /** 密码最后更新时间 */
    private Date pwdUpdateDate;

    public SysUser()
    {

    }

    public SysUser(Long userId)
    {
        this.userId = userId;
    }
}

3、Map缓存实现工具类

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Map 缓存实现
 */
public class MapCache {

    /**
     * 默认存储1024个缓存
     */
    private static final int DEFAULT_CACHES = 1024;

    private static final MapCache INS = new MapCache();

    public static MapCache single() {
        return INS;
    }

    /**
     * 缓存容器
     */
    private final Map<String, CacheObject> cachePool;

    public MapCache() {
        this(DEFAULT_CACHES);
    }

    public MapCache(int cacheCount) {
        cachePool = new ConcurrentHashMap<>(cacheCount);
    }

    /**
     * 读取一个缓存
     *
     * @param key 缓存key
     * @param <T>
     * @return
     */
    public <T> T get(String key) {
        CacheObject cacheObject = cachePool.get(key);
        if (null != cacheObject) {
            long cur = System.currentTimeMillis() / 1000;
            if (cacheObject.getExpired() <= 0 || cacheObject.getExpired() > cur) {
                Object result = cacheObject.getValue();
                return (T) result;
            }
        }
        return null;
    }

    /**
     * 读取一个hash类型缓存
     *
     * @param key   缓存key
     * @param field 缓存field
     * @param <T>
     * @return
     */
    public <T> T hget(String key, String field) {
        key = key + ":" + field;
        return this.get(key);
    }

    /**
     * 设置一个缓存
     *
     * @param key   缓存key
     * @param value 缓存value
     */
    public void set(String key, Object value) {
        this.set(key, value, -1);
    }

    /**
     * 设置一个缓存并带过期时间
     *
     * @param key     缓存key
     * @param value   缓存value
     * @param expired 过期时间,单位为秒
     */
    public void set(String key, Object value, long expired) {
        expired = expired > 0 ? System.currentTimeMillis() / 1000 + expired : expired;
        CacheObject cacheObject = new CacheObject(key, value, expired);
        cachePool.put(key, cacheObject);
    }

    /**
     * 设置一个hash缓存
     *
     * @param key   缓存key
     * @param field 缓存field
     * @param value 缓存value
     */
    public void hset(String key, String field, Object value) {
        this.hset(key, field, value, -1);
    }

    /**
     * 设置一个hash缓存并带过期时间
     *
     * @param key     缓存key
     * @param field   缓存field
     * @param value   缓存value
     * @param expired 过期时间,单位为秒
     */
    public void hset(String key, String field, Object value, long expired) {
        key = key + ":" + field;
        expired = expired > 0 ? System.currentTimeMillis() / 1000 + expired : expired;
        CacheObject cacheObject = new CacheObject(key, value, expired);
        cachePool.put(key, cacheObject);
    }

    /**
     * 根据key删除缓存
     *
     * @param key 缓存key
     */
    public void del(String key) {
        cachePool.remove(key);
    }

    /**
     * 根据key和field删除缓存
     *
     * @param key   缓存key
     * @param field 缓存field
     */
    public void hdel(String key, String field) {
        key = key + ":" + field;
        this.del(key);
    }

    /**
     * 清空缓存
     */
    public void clean() {
        cachePool.clear();
    }

    static class CacheObject {
        private final String key;
        private final Object value;
        private final long expired;

        public CacheObject(String key, Object value, long expired) {
            this.key = key;
            this.value = value;
            this.expired = expired;
        }

        public String getKey() {
            return key;
        }

        public Object getValue() {
            return value;
        }

        public long getExpired() {
            return expired;
        }
    }
}

4、自定义异常类

import com.common.exception.base.BaseException;

/**
 * 用户token相关错误
 */
public class UserTokenInvalidException extends BaseException
{
    private static final long serialVersionUID = 1L;

    public UserTokenInvalidException(String code, Object[] args, String message)
    {
        super("user token invalid", code, args, message);
    }

}

5、shiro 工具类

/**
 * shiro 工具类
 */
public class ShiroUtils
{
    public static Subject getSubject()
    {
        return SecurityUtils.getSubject();
    }

    public static Session getSession()
    {
        return SecurityUtils.getSubject().getSession();
    }

    public static void logout()
    {
        getSubject().logout();
    }

    public static SysUser getSysUser()
    {
        SysUser user = null;
        Object obj = getSubject().getPrincipal();
        if (StringUtils.isNotNull(obj))
        {
            user = new SysUser();
            BeanUtils.copyBeanProp(user, obj);
        }
        return user;
    }

    public static void setSysUser(SysUser user)
    {
        Subject subject = getSubject();
        PrincipalCollection principalCollection = subject.getPrincipals();
        String realmName = principalCollection.getRealmNames().iterator().next();
        PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
        // 重新加载Principal
        subject.runAs(newPrincipalCollection);
    }

    public static Long getUserId()
    {
        return getSysUser().getUserId().longValue();
    }

    public static String getLoginName()
    {
        return getSysUser().getLoginName();
    }

    public static String getIp()
    {
        return getSubject().getSession().getHost();
    }

    public static String getSessionId()
    {
        return String.valueOf(getSubject().getSession().getId());
    }

    /**
     * 生成随机盐
     */
    public static String randomSalt()
    {
        // 一个Byte占两个字节,此处生成的3字节,字符串长度为6
        SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
        String hex = secureRandom.nextBytes(3).toHex();
        return hex;
    }
}

6、登录 and 后端解析用户信息

/**
     * pad端登录
     * @param username 账号
     * @param password 密码
     */
    @PostMapping("/login")
    @ResponseBody
    public AjaxResult login(@NotNull(message = "用户不能为空!")String username,
                               @NotNull(message = "密码不能为空!")String password ,
                               HttpServletRequest request) throws IOException {
        System.out.println("pad登录>>>>userName>>>"+username+">>>password>>>"+password);
        UsernamePasswordToken token = new UsernamePasswordToken(username, password, false);
        Subject subject = SecurityUtils.getSubject();
        try {
            //已有登录验证
            subject.login(token);
            //返回的实体
            loginDto dto = new loginDto();
            dto.setUserId(getUserId().toString());//用户ID
            dto.setToken(UUID.randomUUID().toString());//返回
            System.out.println("【登录获取token】{}"+dto.getToken());
            //缓存token
            setTokenUser(dto.getUserId(),dto.getToken());
            return AjaxResult.success(dto);
        } catch (AuthenticationException e) {
            String msg = "登录名或密码错误";
            return error(msg);
        }
    }

    @PostMapping("/getUser")
    @ResponseBody
    public AjaxResult getUser(){
        System.out.println("【解析访问用户信息】");
        SysUser user = analyticalUser();
        return AjaxResult.success(user);
    }

7、请求接口时,headers请求头带有accessToken参数

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
集成 sa-token 可以让 Spring Boot 应用快速实现权限认证、RBAC、SSO、踢人下线等功能。下面是集成的步骤: 1. 引入 sa-token 的依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>cn.dev33.satoken</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.22.1-RELEASE</version> </dependency> ``` 2. 配置 sa-token 在 application.properties 或 application.yml 文件中添加以下配置: ```yaml # sa-token 配置 sa-token: # token 持久化类型:0-内存版、1-redis版、2-mongodb版、3-jwt版 store-type: 1 # redis 配置 redis: mode: standalone host: 127.0.0.1 port: 6379 database: 0 timeout: 0 # 其他配置... ``` 其中,store-type 表示 sa-token 的持久化类型,可以选择内存版、redis版、mongodb版或 jwt 版。此处选择了 redis 版。 3. 开启 sa-tokenSpring Boot 应用启动类上加上 @SaTokenApplication 注解即可开启 sa-token 的功能: ```java @SpringBootApplication @SaTokenApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } ``` 4. 使用 sa-token 现在,我们可以在代码中使用 sa-token 提供的 API 来实现权限认证、RBAC、SSO、踢人下线等功能了。比如: ```java @RestController public class MyController { // 登录接口 @PostMapping("/login") public String login(String account, String password) { // 模拟登录 if ("admin".equals(account) && "123456".equals(password)) { // 登录成功,生成token String token = SaTokenManager.createToken(account); // 返回token return token; } else { // 登录失败 return "账号或密码错误"; } } // 需要登录才能访问的接口 @GetMapping("/user") public String user() { // 获取当前登录账号 String account = SaTokenManager.getAccount(); // 返回当前登录账号 return "当前登录账号:" + account; } // 需要权限才能访问的接口 @GetMapping("/admin") public String admin() { // 检查是否具有admin角色 boolean isAdmin = SaTokenManager.hasRole("admin"); if (isAdmin) { return "欢迎管理员访问"; } else { return "没有访问权限"; } } // 注销登录接口 @PostMapping("/logout") public String logout() { // 注销登录 SaTokenManager.logout(); return "注销成功"; } } ``` 以上是使用 sa-token 的基本示例,你可以根据自己的需求,使用 sa-token 提供的更多 API 实现更复杂的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值