token的生成和一些基本操作

在前后端分离开发的现在,token是一个必须的技术,虽然不难,但是这篇文章对于小白自己学的话,还是有点用的,以后也可来这进行代码的拷贝啊,四把!
token是对session的一个升级,解决了前后端分离的session不能共享的一个难题,token一般保存与redis中,对于redis的代码书写我也写有文章,可以进行查看,将token存放在redis中,前端每一次请求都会在请求头中存放token,我们只需要进行拿去token就可以进行对比,判断token是否存在,从而验证用户的合法性
话不多说了,来货咯!
这里是tokenservice的接口,定义了一下token的操作

package com.kgc.service.userservice;


import com.kgc.pojo.DmUser;

/*token管理业务接口*/
public interface TokenService {
    /*
     * 会话超时时间,默认2小时
     */
    public final static int SESSION_TIMEOUT=2*60*60;
    /*
     *置换保护时间,默认1小时
     */
    public final static int REPLACEMENT_PROTECTION_TIMEOUT=60*60;
    /*
     *旧token延迟过期时间
     */
    public final static int REPLACEMENT_DELAY=2*60;

    /*
     * 生成token
     * @param agent Http头中的user-agent信息
     * @param user 用户信息
     * @return Token格式<br/>
     *          PC: "前缀PC-USERCODE-USERID-CREATIONDATE-RONDEM[6位]"
     *          <br/>
     *          Android:"前缀ANDOIRD-USERCODE-CREATIONDATE-RONDEM[6位]"
     */
    public String generateToken(String agent, DmUser user) throws Exception;

    /*
     * 保存用于信息至redis
     * @param token token字符串
     * @param user 用户信息
     */
     void save(String token, DmUser user) throws Exception;

    /*
     * 从redis中获取用户信息
     * @param token token字符串
     * @return 对象
     */
    public DmUser load(String token) throws Exception;



    /*
     * 置换token<br/>
     *  1. 首先要判断token是否有效<br/>
     *  2. 生成token后的1个小时内部允许置换<br/>
     *  3. 置换token时, 需要生成新token, 并且旧token不能立即失效,
     *  应设置置换后的时间延长2分钟<br/>
     *  4. 兼容手机端和PC端<br/>
     * @param agent http头信息的user-agent
     * @param token token 字符串
     * @return
     */
    public String replaceToken(String agent, String token) throws Exception;

    /*
     * 验证token是否有效
     * @param agent http头信息的user-agent
     * @param token token 字符串
     * @return
     */
    public boolean validate(String agent, String token) throws Exception;
}

这里是tokenserviceimplement实现的代码,是具体的token的实现

package com.kgc.service.userservice;


import com.alibaba.fastjson.JSON;
import com.kgc.pojo.DmUser;
import com.kgc.utils.MD5;
import com.kgc.utils.RedisUtils;
import com.kgc.utils.UserAgentUtil;
import cz.mallat.uasparser.UserAgentInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/*
 * token管理业务接口实现类
 */
@Service
public class TokenServiceImpl implements TokenService {

    @Autowired
    private RedisUtils redisAPI;/*建立缓存服务器对象*/
    @Override
    /*
    * ticket的生成
    * */
    public String generateToken(String agent, DmUser user) throws Exception {
        StringBuffer sb=new StringBuffer("token:");
        /*获取到请求客户端信息*/
        UserAgentInfo userAgentInfo= null;
        try {
            userAgentInfo = UserAgentUtil.getUasParser().parse(agent);

        //判断发送请求的是否是移动端
        if(userAgentInfo.getDeviceType().equals(UserAgentInfo.UNKNOWN)) {/*未知的*/
            if (UserAgentUtil.CheckAgent(agent)) {
                sb.append("MOBILE-");/*是移动端的*/
            } else {/*不是移动端*/
                sb.append("PC-");
            }
        }else if(userAgentInfo.getDeviceType().equals("Personal computer")){
                sb.append("PC-");
        }else{
            sb.append("MOBILE-");
        }
        if(user.getPhone()!=null){
            sb.append(MD5.getMd5(user.getPhone(),32)+"-");/*将用户的账号进行加密*/
        }else{
            sb.append(user.getSex()+"-");/*将用户的账号进行加密*/
        }
            sb.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+"-");/*生成唯一的ticket*/
            sb.append(MD5.getMd5(agent,6));//对agent进行加密
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
    /*
    * 保存ticket
    * */
    @Override
    public void save(String token, DmUser user) throws Exception {
        if(!redisAPI.exist(token)){/*判断token是否存在*/
            System.out.println(token.startsWith("token: PC-")+"HJKL;");
            if(token.startsWith("token:PC-")){/*判断是否是PC端的*/
                redisAPI.set(token ,TokenService.SESSION_TIMEOUT, JSON.toJSONString(user));
            }else{
                redisAPI.set(token,JSON.toJSONString(user));
            }
        }
    }

    /*
    *
    * 加载token
    * */
    @Override
    public DmUser load(String token) {
        String  Dmuser = (String) redisAPI.get(token);
        return JSON.parseObject(Dmuser,DmUser.class);
    }

    /*
    * 替换token
    *
    * */
    @Override
    public String replaceToken(String agent, String token) throws Exception {
        /*验证token是否存在*/
        if(!redisAPI.exist(token)){
            throw  new Exception("token未知或已过期!");
        }
        /*token存在
         *
         * 将token进行拆分
         * */
        String []tokenDetials=token.split("-");//拆分token为tokenDetials数组
        SimpleDateFormat format=new SimpleDateFormat("yyyyMMddHHmmss");//获取当前时间
        Date tokenGenTime=format.parse(tokenDetials[2]);//获取token中的token生成的时间
        /*获取token生成了的时间*/
        long passed=Calendar.getInstance().getTimeInMillis()-tokenGenTime.getTime();
        /*判断是否token在保护时间内*/
        if(passed< TokenService.REPLACEMENT_PROTECTION_TIMEOUT*1000){
            return ("token还在保护期间,不允许替换");
        }
        //替换token
        String newToken="";
        /*获取到token对应的user对象*/
        DmUser icyUser=this.load(token);
            //创建新的token
            newToken=this.generateToken(agent,icyUser);
            this.save(newToken,icyUser);
            redisAPI.set(token, TokenService.REPLACEMENT_DELAY,JSON.toJSONString(icyUser));
        return newToken;

    }
    /*
    * 验证token
    * */
    @Override
    public boolean validate(String agent, String token)throws Exception  {
        if(!redisAPI.exist(token)){
            return false;
        }
        SimpleDateFormat format=new SimpleDateFormat("yyyyMMddHHmmss");
        String [] tokenDetails=token.split("-");//拆分token
        Date date= null;//获取token中的时间
        try {
            /*date为null,抛出异常*/
            date = format.parse(tokenDetails[2]);

        /*获取token生成时长*/
        long passed=Calendar.getInstance().getTimeInMillis()-date.getTime();
        if(passed> TokenService.SESSION_TIMEOUT*1000){
            return false;/*token失效*/
        }
        String agentMD5=tokenDetails[3];//获取请求头中的token数据
            System.out.println(agentMD5);
        String newAgentM5=MD5.getMd5(agent,6);//对token进行加密
            System.out.println(newAgentM5);
        if(newAgentM5.equals(agentMD5)){
            return true;
        }
    } catch (ParseException e) {
            e.printStackTrace();
    }
        return false;
    }
}

对于有基础的人来说,token实现类中的调用我就不要说啦吧,就是简单的面向对象啊,调用就可以了!
别的就没有咯,要是有兴趣的关注我,博客还有好多哦,我会慢慢写的,当然是我自己学的东西,不具有太高的准确性。哈哈

转载记得加链接!

  • 10
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值