使用JWT实现Token认证

参考: https://www.jianshu.com/p/fe67b4bb6f2c前端

1. 首先按照我本人本身的习惯一个返回类型的类,与token无关,仅仅是为了方便.java

Result.javaweb

package kim.chengcheng.goods.Addition.Token;

import java.io.Serializable;

import io.swagger.annotations.Api;

/**
 *  Controller返回对象定义
 */

public class Result<T> implements Serializable {
	private static final long serialVersionUID = 1L;
	public T result;
	public String code;
	public String msg;
	public boolean success;
	
	public Result(T result, String code, String msg, boolean success) {
		this.result = result;
		this.code = code;
		this.msg = msg;
		this.success = success;
	}
	
	public T getResult() {
		return this.result;
	}

	public void setResult(T result) {
		this.result = result;
	}

	public String getCode() {
		return this.code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getmsg() {
		return this.msg;
	}

	public void setmsg(String msg) {
		this.msg = msg;
	}
	
	public boolean isSuccess() {
		return success;
	}

	public void setSuccess(boolean success) {
		this.success = success;
	}

	public Result() {
	}

	public static <T> Result<T> ok() {
		return new Result<T>(null, "1", null, true);
	}
	
	public static <T> Result<T> ok(T result) {
		return new Result<T>(result, "1", null, true);
	}
	
	public static <T> Result<T> ok(T result, String code) {
		return new Result<T>(result, code, null, true);
	}
	
	public static <T> Result<T> fail(String code) {
		return new Result<T>(null, code, code, false);
	}
	
	public static <T> Result<T> fail(T result, String code) {
		return new Result<T>(result, code, code, false);
	}
	
	public static <T> Result<T> fail(String code, String msg) {
		return new Result<T>(null, code, msg, false);
	}

}

2. 建立JWT生成TOKEN类redis

jwtUtils.java算法

package kim.chengcheng.goods.Addition.Token;

import io.jsonwebtoken.*;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;

/**
 *  用于生成Token,和Token验证
 */
public class JwtUtils {

    public static final String JWT_SECERT = "6ACF4742CAB18FEFE053258E300A7B77";

    /**
     *  建立key
     */
    public static SecretKey generalKey() {

        byte[] encodedKey = Base64.decode(JWT_SECERT);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     * 签发JWT
     * @param subject 能够是JSON数据 尽量少
     */
    public static String createJWT(String subject) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setSubject(subject)   // 主题
                .setIssuer("user")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
//        if (ttlMillis >= 0) {
//            long expMillis = nowMillis + ttlMillis;
//            Date expDate = new Date(expMillis);
//            builder.setExpiration(expDate); // 过时时间
//        }
        return builder.compact();
    }

    /**
     * 验证JWT
     */
    public static Boolean validateJWT(String jwtStr) {
        boolean claims = false;
        try {
            parseJWT(jwtStr);
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return claims;
    }

    /**
     * 解析JWT字符串
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }


}

3.测试类spring

package kim.chengcheng.goods.Addition.Token;

import kim.chengcheng.goods.dao.UsersDao;
import kim.chengcheng.goods.model.Users;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 *  测试Token - JWT签发
 */

@RestController
public class LoginControllerTest {

    private static final Logger logger = LoggerFactory.getLogger(LoginControllerTest.class);

    @Autowired
    UsersDao usersDao;

    // 测试用,若是正式使用则存放到数据库或者是redis中
    private static Map<String,Object> TokenValidation =  new HashMap<String, Object>();

    /**
     *  用户登陆
     */
    @RequestMapping(value="loginTokenTest",method = RequestMethod.POST)
    public Result login(String username, String password,HttpServletResponse
            response) {
        Users users =  usersDao.selectUsers(username);
        if(users != null){
            if(users.getPassword().equals(password)){
                //把token返回给客户端-->客户端保存至cookie-->客户端每次请求附带cookie参数
                String JWT = JwtUtils.createJWT(username);
                TokenValidation.put(JWT, users);  // 存储Toekn
                return Result.ok(TokenValidation);
            }else{
                return Result.fail("500", "用户名或密码错误,请重试");
            }
        }else{
            return Result.fail("500", "无此用户!");
        }
    }

    /**
     * 获取用户信息
     */
    @RequestMapping(value="selectTestsUsers",method = RequestMethod.POST)
    public Result description(String username, HttpServletRequest request) {

        // 从前端获取Header请求头
        String token = request.getHeader("authorization");
        if (null == token || "".equals(token)) {
            return Result.fail("500", "Token不能为空,请从新登陆!!");
        }

        try {
            // 从前端获取到Token令牌去对应的存储位置取
            Object users =  TokenValidation.get(token);
            return Result.ok(users.toString());
        } catch (Exception e) {
            // 若是前端传入的Token令牌和存入的Token令牌不一致,会致使TOken验证失败
            return Result.ok("500", "Token验证失败,请从新登陆!!");
        }

    }
}