淘先锋技术网

首页 1 2 3 4 5 6 7

SSM下的JWT配置

1.简介

随着互联网的不断发展,技术的迭代也非常之快。我们的用户认证也从刚开始的用户名密码转变到基于cookie的session认证,然而到了今天,这种认证已经不能满足与我们的业务需求了(分布式,微服务)。我们采用了另外一种认证方式:基于token的认证。

一、与cookie相比较的优势:

1、支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的;

2、无状态化,服务端无需存储token,只需要验证token信息是否正确即可,而session需要在服务端存储,一般是通过cookie中的sessionID在服务端查找对应的session;

3、无需绑定到一个特殊的身份验证方案(传统的用户名密码登陆),只需要生成的token是符合我们预期设定的即可;

4、更适用于移动端(Android,iOS,小程序等等),像这种原生平台不支持cookie,比如说微信小程序,每一次请求都是一次会话,当然我们可以每次去手动为他添加cookie,详情请查看博主另一篇博客;

5、避免CSRF跨站伪造攻击,还是因为不依赖cookie;

6、非常适用于RESTful API,这样可以轻易与各种后端(java,.net,python…)相结合,去耦合

JWT:JSON Web Token,其实token就是一段字符串,由三部分组成:Header,Payload,Signature。

  • 在微信小程序中,我们可以通过自己定义的Token,来更便捷地定义登录的信息获取
  • 还可以在Shiro中通过自己定义的Token来决定是否允许登录
  • 等等…

2.开始

首先导入对应的maven依赖:

<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.1</version>
        </dependency>

写工具类TokenUtil.java

package com.BookKeeping.util;

import com.BookKeeping.entity.Token;
import com.BookKeeping.entity.User;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenUtil {

    //过期时间设置(30分钟)
    private static final long EXPIRE_TIME = 30*60*1000;

    //私钥设置(随便乱写的)
    private static final String TOKEN_SECRET = "5xcJVrXNyQDIxK1l2RS9nw";

    public String getToken(Token token){

        //过期时间和加密算法设置
        Date date=new Date(System.currentTimeMillis()+EXPIRE_TIME);
        Algorithm algorithm =Algorithm.HMAC256(TOKEN_SECRET);

        //头部信息
        Map<String,Object> header=new HashMap<>(2);
        header.put("typ","JWT");
        header.put("alg","HS256");

        return JWT.create()
                .withHeader(header)
                .withClaim("openId",token.getOpenId())
                .withClaim("role",token.getRole())
                .withClaim("lastLogin",token.getLastLogin())
                .withExpiresAt(date)
                .sign(algorithm);

    }

    public Token getTokenData(String token){
        DecodedJWT jwt = JWT.decode(token);
        Token tk = new Token();

        tk.setOpenId(jwt.getClaim("openId").asString());
        tk.setRole(jwt.getClaim("role").asString());
        tk.setLastLogin(jwt.getClaim("lastLogin").asDate());

        return tk;
    }

    public String creatToken(String openid,String role){
        //这里是传入的是token对象,决定token的内容
        Token tk=new Token();
        //获取时间用
        Date date=new Date();

        tk.setOpenId(openid);
        tk.setRole(role);
        tk.setLastLogin(date);
		//交给上面的实现类得到token
        return getToken(tk);
    }

    public String getTokenDataOpenId(String token){
        return JWT.decode(token).getClaim("openId").asString();
    }
}

token实体类,可以根据需求变更,右键生成get,set,tostring

package com.BookKeeping.entity;
import java.util.Date;
public class Token {
    private Integer id;
    private String openId;
    private String role;
    private Date lastLogin;
}

此时调用creatToken即可获得对应数据得到的token

在测试类中编写如下内容测试:

    @Test
    //Token加解密测试
    public void TokenTest(){
        TokenUtil tku=new TokenUtil();
        Token tk=new Token();

        String result=tku.creatToken("asdfghjkl","admin");

        System.out.println(result);

        tk=tku.getTokenData(result);

        System.out.println(tk.toString());
    }

结果:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsYXN0TG9naW4iOjE1ODA0NDM0NTYsInJvbGUiOiJhZG1pbiIsIm9wZW5JZCI6ImFzZGZnaGprbCIsImV4cCI6MTU4MDQ0NTI1Nn0.a3DRBuM2g_BODTf142RO6JWAMPVE3voJZvuWSioX_Yo
Token{id=null, openId='asdfghjkl', role='admin', lastLogin=Fri Jan 31 12:04:16 GMT+08:00 2020}