springBoot整合jwt实现token令牌认证的示例代码

 更新时间:2024年08月12日 10:19:15   作者:小白写代码hh  
实施Token验证的方法挺多的,还有一些标准方法,比如JWT,本文主要介绍了springBoot整合jwt实现token令牌认证的示例代码,具有一定的参考价值,感兴趣的可以了解一下

1. 什么token

作为计算机术语时,是“令牌”的意思。Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

使用token机制的身份验证方法,在服务器端不需要存储用户的登录记录。

大概的流程:

1   客户端使用用户名和密码请求登录。

2   服务端收到请求,验证用户名和密码。

3   验证成功后,服务端会生成一个token,然后把这个token发送给客户端。

4   客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。

5   客户端每次向服务端发送请求的时候都需要带上服务端发给的token。

6    服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据

2. jwt是什么

实施 Token 验证的方法挺多的,还有一些标准方法,比如 JWT,读作:jot ,表示:JSON Web Tokens 。JWT 标准的 Token 有三个部分:

1. header(头部),头部信息主要包括(参数的类型--JWT,签名的算法--HS256)
2. poyload(负荷),负荷基本就是自己想要存放的信息(因为信息会暴露,不应该在载荷里面加入任      何敏感的数据)
3. sign(签名),签名的作用就是为了防止恶意篡改数据,

例如:中间用点分隔开,并且都会使用 Base64 编码,所以真正的 Token 看起来像这样:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.//头部
eyJpZCI6IjIiLCJleHAiOjE3MDI0NDE3MDcsInVzZXJuYW1lIjoiYWRtaW4ifQ.//负载
k8F9h5GQB1-rTVi-8hs9jOWnfpJALSk2Y08xeZb7YlE//签名

3. jwt的依赖坐标

springboot引入jwt:

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

4. springboot整合token

在这里只是给大家一个演示,
首先要知道如何生成一个token 那就是上面讲到的请求头+负载+签名

package com.hyh.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.hyh.domain.User;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Calendar;
import java.util.Date;

public class JwtUtil {
    // 生成token
    // Algorithm.HMAC256():使用HS256生成token,密钥则是用户的密码
    private static final String SING = "MusicProject";

    public String getToken(User user) {
        //System.out.println(String.valueOf(user.getId()));
        // 设置token过期时间
        Calendar instance= Calendar.getInstance();
        instance.add(Calendar.DATE,7);
        String token="";
        token= JWT.create()
                .withClaim("id",String.valueOf(user.getId())) //设置载荷
                .withClaim("username",user.getUsername())
                .withExpiresAt(instance.getTime()) //设置令牌过期的时间
                .sign(Algorithm.HMAC256(SING));

        return token;
    }
    /**,
     * 验证token  合法性
     */
    public static DecodedJWT verify(String token) {
        return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }
}

我把生成token的方法和验证方法弄成了一个工具类 
在这里我定义的签名是静态变量 可以根据自己需求来定义 这里的id是从数据库里面拿到的 这里的验证token符合的话就放行,否则就抛异常。

接下来就需要配置一个拦截器 对于拦截请求资源

public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
    UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();

        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(TokenRequired.class)) {
            TokenRequired userLoginToken = method.getAnnotation(TokenRequired.class);
            if (userLoginToken.required()) {

                Map<String,Object> map = new HashMap<>();
                // 获取请求头中令牌
                System.out.println(token);
                try {
                    // 验证令牌
                    JwtUtil.verify(token);
                    return true;  // 放行请求
                } catch (SignatureVerificationException e) {
                    e.printStackTrace();
                    map.put("msg","无效签名!");
                }catch (TokenExpiredException e){
                    e.printStackTrace();
                    map.put("msg","token过期");
                }catch (AlgorithmMismatchException e){
                    e.printStackTrace();
                    map.put("msg","算法不一致");
                }catch (Exception e){
                    e.printStackTrace();
                    map.put("msg","token无效!");
                }
                map.put("state",false);  //设置状态
                // 将map以json的形式响应到前台  map --> json  (jackson)
                String json = new ObjectMapper().writeValueAsString(map);
                httpServletResponse.setContentType("application/json;charset=UTF-8");
                httpServletResponse.getWriter().println(json);
                return false;

            }
        }
        return true;
    }

在这里面 useservice是我自己的实现类,里面可以查到用户id

把拦截器注册:

@Configuration  // 配置类
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthenticationInterceptor())
                .addPathPatterns("/api/**")  // 拦截所有请求
                .excludePathPatterns("/api/login","/api/register");  // 放行登录 注册
    }
}

这里因为拦截了所有请求 但是我们可以自己定义一个注解来判断当我们请求资源的时候需不需呀token验证。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenRequired {
    boolean required() default true;
}

当我们在某个资源上加上了这个注解 说明这个资源需要token验证

这是我写的一个登录接口 集成了验证码功能

/*
     * @description: 用户的登录
     * @param: User user
     * @return:result
     * @author
     * @date: 2023/9/28 10:03
     */
    @PostMapping("/login")
    public Result login(@RequestBody User user,HttpSession httpSession,HttpServletResponse response){
        String checkCode = (String) httpSession.getAttribute("checkCode");
        System.out.println(checkCode);
        if (user.getCheCode() == null || !user.getCheCode().equalsIgnoreCase(checkCode)) {
            return new Result(Code.Err, null, "验证码错误");
        }

        boolean flag = userService.selectUsernamePwd(user);
        boolean is_exist = userService.selectByName(user.getUsername());
        if (flag) {
            JwtUtil jwtUtil = new JwtUtil();
            User user1 = userService.selectByNameToken(user.getUsername());
            String token = jwtUtil.getToken(user1);
            user.setToken(token);
            Cookie cookie = new Cookie("username",user.getUsername());
            cookie.setMaxAge(60*60*24*7);
            cookie.setPath("/");
            response.addCookie(cookie);
            httpSession.setAttribute("username", user.getUsername());
            return new Result(Code.Ok,user,"登录成功");
        }else if(!is_exist){
            return new Result(Code.Err,user,"登录失败 用户不存在");
        }else{
            return new Result(Code.Err,user,"登录失败");
        }
    }

这个资源是需要token验证访问的资源 加了注解 @TokenRequired

   @GetMapping
    @TokenRequired
    public Result selectAllSingers(HttpServletRequest request) {
        List<Singer> singers = songService.selectSingerAll();
        Integer code = singers != null ? Code.Ok : Code.Err;
        String msg = singers != null ? "" : "数据查询失败 请重试";
        return new Result(code, singers, msg);
    }

当我们没有token的时候正常访问一下:

可以看到是无法访问的 

我们可以先登录获取token 在进行访问试一下

因为我把token封装在user里面 所以返回了token 现在把token放到刚刚无法访问的url的请求头里,再次访问一下:

现在访问有数据了 这些数据都是我自己封装好的,你自己可以随便写写字符串返回来进行测试。

到此这篇关于springBoot整合jwt实现token令牌认证的示例代码的文章就介绍到这了,更多相关springBoot token令牌认证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java制作专属智能陪聊机器人详解

    java制作专属智能陪聊机器人详解

    人工智能一直是最近的热点话题,,这篇文章主要为大家详细介绍了java实现智能陪聊机器人,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • SpringBoot中application.properties与application.yml区别小结

    SpringBoot中application.properties与application.yml区别小结

    本文主要介绍了SpringBoot中application.properties与application.yml区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-10-10
  • Java+element实现excel的导入和导出

    Java+element实现excel的导入和导出

    本文主要介绍了Java+element实现excel的导入和导出,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 详解Java中字典树(Trie树)的图解与实现

    详解Java中字典树(Trie树)的图解与实现

    Trie又称为前缀树或字典树,是一种有序树,它是一种专门用来处理串匹配的数据结构。本文将利用图解详细讲解Trie树的实现,需要的可以参考一下
    2022-05-05
  • 详解Java中NullPointerException的处理方法

    详解Java中NullPointerException的处理方法

    这篇文章将带大家来单独看一个很常见的异常--空指针异常,这个可以说是每个Java程序员都必知的异常,所以我们不得不单独学习一下,文中有详细的代码示例,需要的朋友可以参考下
    2023-08-08
  • 用java实现跳动的小球示例代码

    用java实现跳动的小球示例代码

    这篇文章主要介绍了用java实现跳动的小球,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • java实战之猜字小游戏

    java实战之猜字小游戏

    这篇文章主要介绍了java实战之猜字小游戏,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助呦,需要的朋友可以参考下
    2021-04-04
  • Java正确实现一个单例设计模式的示例

    Java正确实现一个单例设计模式的示例

    今天小编就为大家分享一篇关于Java正确实现一个单例设计模式的示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • swagger文档增强工具knife4j使用图文详解

    swagger文档增强工具knife4j使用图文详解

    这篇文章主要介绍了swagger文档增强工具knife4j使用详解,想要使用knife4j非常简单,只要在Springboot项目中引入knife4j的依赖即可,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • 如何在SpringBoot中使用Spring-AOP实现接口鉴权

    如何在SpringBoot中使用Spring-AOP实现接口鉴权

    这篇文章主要介绍了如何在SpringBoot中使用Spring-AOP实现接口鉴权,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2022-09-09

最新评论