redis实现token机制

 token机制原理图

 下面是实现token机制的代码

项目结构图(springboot项目)

pom.xml文件

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.1.0</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.31</version>
		</dependency>
		<dependency>
			<groupId>nl.bitwalker</groupId>
			<artifactId>UserAgentUtils</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.6</version>
		</dependency>

redis.properties文件

#访问地址
redis.host=192.168.126.130
#访问端口
redis.port=6379  
#注意,如果没有password,此处不设置值,但这一项要保留
redis.pass=123456
#超时时间
redis.timeout=60
#使用哪个数据库
redis.default.db=0

#最大空闲时间,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
redis.maxIdle=300  
#连接池的最大数据库连接数。设为0表示无限制
redis.maxActive=600  
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWait=1000  
#在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
redis.testOnBorrow=true 

applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:property-placeholder location="classpath:redis.properties"/>

    <!-- 配置JedisPoolConfig实例 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxActive" value="${redis.maxActive}" />
        <property name="maxWait" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
   <!-- 配置JedisPool实例 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy">
        <constructor-arg ref="jedisPoolConfig" />
        <constructor-arg value="${redis.host}" />
        <constructor-arg value="${redis.port}" />
        <constructor-arg value="${redis.timeout}" />
        <constructor-arg value="${redis.pass}" />
        <constructor-arg value="${redis.default.db}" />
    </bean>
    <bean id="redisUtil" class="com.fengqing.af.util.RedisUtil">
        <property name="jedisPool" ref="jedisPool" />
    </bean>
</beans>

User.java

package com.fengqing.af.bean;

public class User{
    private Integer id;

    private String username;

    private String password;

    public User() {
    }

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Dto.java

package com.fengqing.af.bean;

public class Dto {
    private String token;

    //token创建时间
    private Long tokenCreatedTime;

    //失效时间
    private Long tokenExpiryTime;

    private String isLogin;

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public Long getTokenCreatedTime() {
        return tokenCreatedTime;
    }

    public void setTokenCreatedTime(Long tokenCreatedTime) {
        this.tokenCreatedTime = tokenCreatedTime;
    }

    public Long getTokenExpiryTime() {
        return tokenExpiryTime;
    }

    public void setTokenExpiryTime(Long tokenExpiryTime) {
        this.tokenExpiryTime = tokenExpiryTime;
    }

    public String getIsLogin() {
        return isLogin;
    }

    public void setIsLogin(String isLogin) {
        this.isLogin = isLogin;
    }
}

RedisUtil.java

package com.fengqing.af.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisUtil {
    private JedisPool jedisPool;

    public void setJedisPool(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    //添加
    public void set(String key, String value){
        Jedis jedis = this.jedisPool.getResource();
        jedis.set(key, value);
        this.jedisPool.returnResource(jedis);
    }

    //添加,带超时时间
    public void setex(String key, int seconds, String value){
        Jedis jedis = this.jedisPool.getResource();
        jedis.setex(key, seconds, value);
        this.jedisPool.returnResource(jedis);
    }

    //获取
    public String get(String key){
        Jedis jedis = this.jedisPool.getResource();
        String value = jedis.get(key);
        this.jedisPool.returnResource(jedis);
        return value;
    }

    //查看某个键是否存在
    public boolean exists(String key){
        Jedis jedis = this.jedisPool.getResource();
        Boolean exists = jedis.exists(key);
        this.jedisPool.returnResource(jedis);
        return exists;
    }

    //查看超时时间
    public Long ttl(String key){
        Jedis jedis = this.jedisPool.getResource();
        Long ttl = jedis.ttl(key);
        this.jedisPool.returnResource(jedis);
        return ttl;
    }

    //删除
    public void del(String key){
        Jedis jedis = this.jedisPool.getResource();
        jedis.del(key);
        this.jedisPool.returnResource(jedis);
    }
}

TokenService.java

package com.fengqing.af.service;

import com.alibaba.fastjson.JSONObject;
import com.fengqing.af.bean.User;
import com.fengqing.af.util.RedisUtil;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

@Service("tokenService")
public class TokenService {
    private RedisUtil redisUtil;

    public TokenService(){
        init();
    }

    private void init() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        redisUtil = (RedisUtil)applicationContext.getBean("redisUtil");
    }

    //生成token(格式为token:设备-加密的用户名-时间-六位随机数)
    public String generateToken(String userAgent, String username){
        StringBuilder token = new StringBuilder();
        //加token:
        token.append("token:");
        //加设备
        UserAgent userAgent1 = UserAgent.parseUserAgentString(userAgent);
        if (userAgent1.getOperatingSystem().isMobileDevice()){
            token.append("MOBILE-");
        } else {
            token.append("PC-");
        }
        //加加密的用户名
        token.append(DigestUtils.md5Hex(username) + "-");
        //加时间
        token.append(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + "-");
        //加六位随机数111111-999999
        token.append(new Random().nextInt((999999 - 111111 + 1)) + 111111);
        System.out.println("token=>" + token.toString());
        return token.toString();
    }

    //保存token
    public void saveToken(String token, User user){
        //如果是PC,那么token保存两个小时;如果是MOBILE
        if (token.startsWith("token:PC")) {
            redisUtil.setex(token,2*60*60, JSONObject.toJSONString(user));
        } else {
            redisUtil.set(token, JSONObject.toJSONString(user));
        }
    }
}

UserService.java

package com.fengqing.af.service;

import com.fengqing.af.bean.User;

import org.springframework.stereotype.Service;

@Service("userService")
public class UserService {


    public User login(String username, String password){
        //假设数据库有个用户用户名为fengqing,密码为123456
        if ("fengqing".equals(username) && "123456".equals(password)){
            return new User(1, "fengqing", "123456");
        } else {
            return null;
        }
    }

}

UserController.java

package com.fengqing.af.controller;

import com.alibaba.fastjson.JSONObject;
import com.fengqing.af.bean.Dto;
import com.fengqing.af.bean.User;
import com.fengqing.af.service.TokenService;
import com.fengqing.af.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private TokenService tokenService;

    @RequestMapping("/login")
    @ResponseBody
    public String login(String username, String password, HttpServletRequest request){
        Dto dto = new Dto();

        User user = this.userService.login(username, password);
        if (user != null) {//登录成功生成token并保存token
            String userAgent = request.getHeader("user-agent");
            String token = this.tokenService.generateToken(userAgent, username);
            this.tokenService.saveToken(token, user);

            dto.setIsLogin("true");
            dto.setToken(token);
            dto.setTokenCreatedTime(System.currentTimeMillis());
            dto.setTokenExpiryTime(System.currentTimeMillis() + 2*60*60*1000);

        } else {
            dto.setIsLogin("false");
        }
        return JSONObject.toJSONString(dto);
    }
}

猜你喜欢

转载自blog.csdn.net/fengqing5578/article/details/82183760
今日推荐