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及数据库验证

原文地址:https://www.cnblogs.com/zhaogaojian/p/12164349.html

时间: 2024-10-27 17:29:46

SpringBoot学习- 4、整合JWT的相关文章

玩转 SpringBoot 2 之整合 JWT 上篇

前言 该文主要带你了解什么是 JWT,以及JWT 定义和先关概念的介绍,并通过简单Demo 带你了解如何使用 SpringBoot 2 整合?JWT. 介绍前在这里我们来探讨一下如何学习一门新的技术,我个人总结为 RSA. R:read 去读官方文档 . S:search 谷歌或百度先关技术文章或 github 去搜索先关信息. A:ask 可以向技术大牛请教或和自己的同事同学进行探讨. 关于?RSA 仅仅代码个人的学习观点,只是给读者一个不成熟的小建议哈 JWT 介绍 官网介绍如下: What

玩转 SpringBoot 2 之整合 JWT 下篇

前言 在<玩转 SpringBoot 2 之整合 JWT 上篇> 中介绍了关于 JWT 相关概念和JWT 基本使用的操作方式.本文为 SpringBoot 整合 JWT 的下篇,通过解决 App 用户登录 Session 问题的实战操作,带你更深入理解 JWT.通过本文你还可以了解到如下内容: SpringBoot 使用拦截器的实际应用 SpringBoot 统一异常处理 SpringBoot 快速搭建 RESTful Api 关于生成JWT 操作请参考 <玩转 SpringBoot 2

SpringBoot学习:整合Mybatis,使用HikariCP超高性能数据源

一.添加pom依赖jar包: 1 <!--整合mybatis--> 2 <dependency> 3 <groupId>org.mybatis.spring.boot</groupId> 4 <artifactId>mybatis-spring-boot-starter</artifactId> 5 <version>1.1.1</version> 6 </dependency> 7 8 <!

SpringBoot学习--04SpringBoot整合Mybatis(上)(配置mybatis generator,PageHelper)

陆陆续续又忙了几天,继续写. 本篇仿照着优秀的文章的书写,加上自己的理解和踩过的坑,原文地址:https://www.jianshu.com/p/5cd772c07041?utm_campaign=haruki&utm_content=note&utm_medium=reader_share&utm_source=weixin 环境/版本一览: 开发工具:eclipse springboot: 2.0.1.RELEASE jdk:1.8.0_40 maven:3.3.9 额外功能:

SpringBoot学习10:springboot整合mybatis

需求:通过使用 SpringBoot+SpringMVC+MyBatis 整合实现一个对数据库中的 t_user 表的 CRUD 的操作 1.创建maven项目,添加项目所需依赖 <!--springboot项目依赖的父项目--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId>

SpringBoot学习- 8、整合Shiro

Shiro是什么,引自百度百科:Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序. 关于Shiro网上讲的很多,以下代码是来自网上几篇博客文章的代码集成, 下面是集成步骤 1.pom.xml添加以下内容 <dependency> <groupId>org.apache.shiro</groupId> <

Spring Security 整合JWT(四)

一.前言 本篇文章将讲述Spring Security 简单整合JWT 处理认证授权 基本环境 spring-boot 2.1.8 mybatis-plus 2.2.0 mysql 数据库 maven项目 Spring Security入门学习可参考之前文章: SpringBoot集成Spring Security入门体验(一)https://blog.csdn.net/qq_38225558/article/details/101754743 Spring Security 自定义登录认证(二

springboot+mybatis+springmvc整合实例

以往的ssm框架整合通常有两种形式,一种是xml形式,一种是注解形式,不管是xml还是注解,基本都会有一大堆xml标签配置,其中有很多重复性的.springboot带给我们的恰恰是"零配置","零配置"不等于什么也不配置,只是说相对于传统的ssm框架的xml配置或是注解配置,要少的多.作为常规的来说,一个ssm框架整合,拿maven来说,首先在src/main/resource下加入jdbc.properties,spring-mvc.xml,spring-myba

Spring Security整合JWT,实现单点登录,So Easy~!

前面整理过一篇 SpringBoot Security前后端分离,登录退出等返回json数据,也就是用Spring Security,基于SpringBoot2.1.4 RELEASE前后端分离的情况下,实现了登陆登出的功能,亮点就在于以JSON的形式接收返回参数.这个是针对单个后台服务的, 登录信息都存储在SecurityContextHolder缓存里.如果是两个或两个以上的应用呢,那该怎么办?Session是不能用了,Cookie自然也不能用,毕竟它俩是一对的. 曾想过用OAuth2来解决

springboot学习笔记(一)

在我看来,spring-boot 的好处在于能快速的搭建起一个项目的框架 ,省略了繁琐的xml配置,能通过spring boot Application类快速启动工程 快速搭建spring-boot-web: 工具:eclipse+maven+jdk1.8 1.创建maven工程,在pom.xml文件中加入需要依赖的jar包,spring-boot帮我们整合了一些默认的设置在spring-boot-starter-parent, 1.使用java6编译级别 2.使用utf-8编码 3.实现了通用