SpringBoot学习- 4、整合JWT

1、Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

2、pom.xml增加如下代码来添加JWT依赖包

<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.9.0</version>
</dependency>

3、IDEA2019.3版本中文乱码,设置UTF-8不起作用,修改字体如下

以下几部分内容主要参考
https://www.cnblogs.com/30go/p/10963924.html
https://www.jianshu.com/p/9af8612f6aef

 4、在Utils文件夹下增加TokenUtil

RefreshToken暂不使用

package com.jgui.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.jgui.domain.JUser;

import java.util.Date;

/**
 * @Author: zhaogaojian
 * @Description:
 * @Date: Created in 2020/1/722:13
 */
public class TokenUtil {
    private static final long TOKEN_EXPIRE_TIME= 30*60*1000;//超时时间30分钟
    private static final long REFRESH_TOKEN_EXPIRE_TIME= 15*24*60*1000;//超时时间15天
    private static final String TOKEN_SECRET="jguiafadfiierpewirpew8908ewrq";//秘钥
    private static final String ISSUER="jgadmin";//签发人
    /**
     * 签名生成
     * @param user
     * @return
     */
    public static String sign(JUser user){

        String token = "";
        try {
            Date expiresAt = new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME);
            Date now = new Date();
            token = JWT.create()
                    .withIssuer(ISSUER)
                    .withClaim("username", user.getUsername())
                    .withExpiresAt(expiresAt)
                    .withIssuedAt(now)
                    // 使用了HMAC256加密算法。
                    .sign(Algorithm.HMAC256(TOKEN_SECRET));
        } catch (Exception e){
            e.printStackTrace();
        }
        return token;

    }
    /**
     * 签名验证
     * @param token
     * @return
     */
    public static boolean verify(String token){
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
            DecodedJWT jwt = verifier.verify(token);
            System.out.println("认证通过:");
            System.out.println("issuer: " + jwt.getIssuer());
            System.out.println("username: " + jwt.getClaim("username").asString());
            System.out.println("签发时间:" + jwt.getIssuedAt());
            System.out.println("过期时间:" + jwt.getExpiresAt());
            return true;
        } catch (Exception e){
            return false;
        }

    }
    /**
     * 从token获取username
     */
    public static String getUsername(String token){
        try{
            return JWT.decode(token).getClaim("username").asString();
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return "";
    }
}
package com.jgui.utils;

import java.util.UUID;

/**
 * @Author: zhaogaojian
 * @Description:
 * @Date: Created in 2020/1/722:50
 */
public class StringUtil {
    public static String GetUUIDString()
    {
       return UUID.randomUUID().toString();
    }

}

5、在Controller下增加LoginController

package com.jgui.controller;

import com.jgui.dao.JUserDao;
import com.jgui.domain.JUser;
import com.jgui.utils.StringUtil;
import com.jgui.utils.TokenUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author: zhaogaojian
 * @Description:
 * @Date: Created in 2020/1/722:38
 */
@RestController
public class LoginController {
    @Resource
    private JUserDao userDao;
    @GetMapping("/login")
    public Map<String,Object> login(@RequestParam String username, @RequestParam String password) {

        if("zhangsan".equals(username) && "123".equals(password)){
            JUser user=new JUser();
            user.setUsername("zhangsan");
            user.setRealname("张三");
            Map<String,Object> map = new HashMap<>();
            //生成token
            String token = TokenUtil.sign(user);
            String refreshToken = StringUtil.GetUUIDString();
            if(token != ""){
                map.put("code", "10000");
                map.put("message", "认证成功");
                map.put("token", token);
                map.put("refreshtoken", refreshToken);
                return map;
            }
        }
        Map<String,Object> map = new HashMap<>();
        map.put("code", "10001");
        map.put("message", "认证失败");
        map.put("token", "");
        map.put("refreshtoken", "");
        return map;
    }
}

6、在Interceptor目录下增加TokenInterceptor

package com.jgui.interceptor;
import com.jgui.utils.TokenUtil;
import net.minidev.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
/**
 * @Author: zhaogaojian
 * @Description:
 * @Date: Created in 2020/1/723:12
 */
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{

        if(request.getMethod().equals("OPTIONS")){
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        String token = request.getHeader("token");
        if(token != null){
            boolean result = TokenUtil.verify(token);
            if(result){
                System.out.println("通过拦截器");
                return true;
            }
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = null;
        try{
            JSONObject json = new JSONObject();
            json.put("success","false");
            json.put("msg","认证失败,未通过拦截器");
            json.put("code","10003");
            response.getWriter().append(json.toJSONString());
            System.out.println("认证失败,未通过拦截器");
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
            return false;
        }
        return false;

    }

}

7、在config下增加InterceptorConfig

package com.jgui.config;

/**
 * @Author: zhaogaojian
 * @Description:
 * @Date: Created in 2020/1/723:15
 */
import com.jgui.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
 * 拦截器配置
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    private TokenInterceptor tokenInterceptor;
    //构造方法
    public InterceptorConfig(TokenInterceptor tokenInterceptor){
        this.tokenInterceptor = tokenInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        List<String> excludePath = new ArrayList<>();
        excludePath.add("/user_register"); //注册
        excludePath.add("/login"); //登录
        excludePath.add("/logout"); //登出
        excludePath.add("/static/**");  //静态资源
        excludePath.add("/assets/**");  //静态资源

        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

8、运行项目

可以发现之前的http://localhost:8080/Hello

访问时会因为拦截器而导致无法访问

login接口因为被排除在拦截器外可以访问

 

 以上内容主要参考
https://www.cnblogs.com/30go/p/10963924.html
https://www.jianshu.com/p/9af8612f6aef

下一节将增加Redis及数据库验证

猜你喜欢

转载自www.cnblogs.com/zhaogaojian/p/12164349.html