当前位置:

首页 > 编程开发 > Spring Boot怎么集成JWT实现前后端认证

Spring Boot怎么集成JWT实现前后端认证

JWT简介JWT(全称:JsonWebToken)是一个开放标准(RFC7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。为什么要用JWT传统session认证存在那些弊端?每个用户的登录信息都会保存到服务器的Session中,随着用户的增多,服务器开销会明显增大。Session的信息存放在服务器的内存中,对于分布式应用会导致失效,虽然可以将session的信息统一存放在Redis的缓存中,但这样可能增加了复杂性。由于Session认证是基于Cookie实现,而针

本文目录

    JWT简介

    JWT(全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。

    为什么要用JWT

    传统session认证存在那些弊端?

    • 每个用户的登录信息都会保存到服务器的Session中,随着用户的增多,服务器开销会明显增大。

    • Session的信息存放在服务器的内存中,对于分布式应用会导致失效,虽然可以将session的信息统一存放在Redis的缓存中,但这样可能增加了复杂性。

    • 由于Session认证是基于Cookie实现,而针对于非浏览器端和手机的移动端都不适用。

    • 前后端分离系统,由于前后端存在跨域,而Cookie信息无法跨越,所以采用Session认证也是无法继续宁跨域认证。

    JWT认证的优势

    • 简洁:JWT Token数据量小,传输速度也很快。

    • 跨语言: JWT Token是以JSON加密形式保存在客户端的,所以JWT是跨语言的,任何web形式都支持。 跨平台:不依赖于cookie和session,无需将session信息存放在服务端,非常适合于分布式应用,应用于扩展。

    JWT的数据结构

    Spring Boot怎么集成JWT实现前后端认证

    Header

    JWT第一部分是头部分,它是一个描述JWT元数据的Json对象,通常如下所示。

    {
        "alg": "HS256",
        "typ": "JWT"
    }

    alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256),typ属性表示令牌的类型,JWT令牌统一写为JWT。

    Payload

    JWT第二部分是Payload,也是一个Json对象,除了包含需要传递的数据,还有七个默认的字段供选择。 iss:发行人 exp:到期时间 sub:主题 aud:用户 nbf:在此之前不可用 iat:发布时间 jti:JWT ID用于标识该JWT

    {
        //默认字段
        "sub":"主题123",
        //自定义字段
        "name":"java",
        "isAdmin":"true",
        "loginTime":"2021-12-05 12:00:03"
    }

    需要注意的是,默认情况下JWT是未加密的,任何人都可以解读其内容,因此如果一些敏感信息不要存放在此,以防信息泄露。JSON对象也使用Base64 URL算法转换为字符串保存。

    Signature

    签名哈希部分是对上面两部分数据签名,需要使用base64编码后的header和payload数据,通过指定的算法生成哈希,以确保数据不会被篡改。

    Spring Boot集成JWT

    引入Jwt包

    
            io.jsonwebtoken
            jjwt
            0.9.1
      

    编写jwt工具类

    public class JwtUtil
    {
    //创建jwt
    public static String createJWT(String subject, String issue, Object claim,
                long ttlMillis)
        {
           //当前时间
            long nowMillis = System.currentTimeMillis();
            //过期时间
            long expireMillis = nowMillis + ttlMillis;
            String result = Jwts.builder()
                    .setSubject(subject) //设置主题
                    .setIssuer(issue) //发行者
                    .setId(issue)//jwtID
                    .setExpiration(new Date(expireMillis)) //设置过期日期
                    .claim("user", claim)//主题,可以包含用户信息
                    .signWith(getSignatureAlgorithm(), getSignedKey())//加密算法
                    .compressWith(CompressionCodecs.DEFLATE).compact();//对载荷进行压缩
    
            return result;
        }
        
        // 解析jwt
        public static Jws pareseJWT(String jwt)
        {
            Jws claims;
            try
            {
                claims = Jwts.parser().setSigningKey(getSignedKey())
                        .parseClaimsJws(jwt);
            }
            catch (Exception ex)
            {
                claims = null;
            }
            return claims;
        }
    
       //获取主题信息
        public static Claims getClaims(String jwt)
        {
            Claims claims;
            try
            {
                claims = Jwts.parser().setSigningKey(getSignedKey())
                        .parseClaimsJws(jwt).getBody();
            }
            catch (Exception ex)
            {
                claims = null;
            }
            return claims;
        }
      }
      
       /**
         * 获取密钥
         * 
         * @return Key
         */
        private static Key getSignedKey()
        {
            byte[] apiKeySecretBytes = DatatypeConverter
                    .parseBase64Binary(getAuthKey());
            Key signingKey = new SecretKeySpec(apiKeySecretBytes,
                    getSignatureAlgorithm().getJcaName());
            return signingKey;
        }
        
        private static SignatureAlgorithm getSignatureAlgorithm()
        {
            return SignatureAlgorithm.HS256;
        }
      
      //获取密钥,可以动态配置
      public static String getAuthKey()
      {
            String auth = "123@#1234";
      }

    Token认证拦截器

     Component
    public class TokenInterceptor extends HandlerInterceptorAdapter
    {
        public static Log logger = LogManager.getLogger(TokenInterceptor.class);
    
        @Override
        public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception
        {
            String uri = request.getRequestURI();
            logger.info("start TokenInterceptor preHandle.." + uri);
             
    		//需要过滤特殊请求
            if (SystemUtil.isFree(uri) || SystemUtil.isProtected(uri))
            {
                return true;
            }
            
    		
            String metohd=request.getMethod().toString();
            logger.info("TokenInterceptor request method:"+metohd);
            //options 方法需要过滤
            if("OPTIONS".equals(metohd))
            {
                return true;   
            }
            
    		//是否开启token认证
            boolean flag = SystemUtil.getVerifyToken();
            ResponseResult result = new ResponseResult();
    		//从请求的head信息中获取token
            String token = request.getHeader("X-Token");
    
            if (flag)
            {
                if(StringUtils.isEmpty(token))
                {
                    token=request.getParameter("X-Token");    
                }
                // token不存在
                if (StringUtils.isEmpty(token))
                {
                    result.setCode(ResultCode.NEED_AUTH.getCode());
                    result.setMsg(ResultCode.NEED_AUTH.getMsg());
                    WebUtil.writeJson(result, response);
                    return false;
                }
                else
                {
                    Claims claims = JwtUtil.getClaims(token);
                    String subject = "";
                    if (claims != null)
                    {
                        subject = claims.getSubject();
                        // 验证主题
                        if (StringUtils.isEmpty(subject))
                        {
                            result.setCode(ResultCode.INVALID_TOKEN.getCode());
                            result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                            WebUtil.writeJson(result, response);
                            return false;
                        }								
                    }
                    else
                    {
                        result.setCode(ResultCode.INVALID_TOKEN.getCode());
                        result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                        WebUtil.writeJson(result, response);
                        return false;
                    }
                }
            }
            return true;
        }
    
    }

    配置拦击器

    @Configuration
    public class WebConfig implements WebMvcConfigurer
    {
        @Resource
        private TokenInterceptor tokenInterceptor;
    
        public void addInterceptors(InterceptorRegistry registry)
        {
            registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
        }
     }

    登录验证流程

    Spring Boot怎么集成JWT实现前后端认证

    示例代码

    @RequestMapping("login")
    public Result login(HttpServletResponse response)
    {
        Map map = new HashMap<>();
        //
        Result result = loginAuth(user);
        int code = result.getCode();
                //登录认证成功
        if (code ==ResultCode.SUCCESS)
        {
            //默认为7天
            Long ttlMillis = 7*1000 * 60 * 60 * 24;
            //过期时间
            long expreTime = System.currentTimeMillis() + ttlMillis;
            String tokenKey = UUID.randomUUID().toString();
            String tokenId = JwtUtil.createJWT(user.getUserId(), tokenKey,
                    user.getPassword(), expreTime);                   
            map.put("expreTime", expreTime);				
            map.put("tokenId", tokenId);           
        }
        else
        {
            logger.error("login error:" +FastJsonUtil.toJSONString(result));
        }
        return result;
    }
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    Golang JWT验证实战,gin-jwt库使用教程
    Golang JWT验证实战,gin-jwt库使用教程

    如何在Golang中实现JWT身份验证?最常用的方法是使用gin-jwt库。步骤包括:1.安装gin和gin-jwt库;2.定义用户数据结构,如User;3.创建JWT中间件并配置密钥、过期时间、PayloadFunc、IdentityHandler、Authenticator、Authorizator等参数;4.配置路由,将LoginHandler和RefreshHandler绑定到对应路径,并对需认证的接口应用中间件;5.选择合适的JWT库时应考虑性能、安全性、易用性和社区支持;6.确保JWT安全需使

    PHP实现JWT白名单验证方法详解
    PHP实现JWT白名单验证方法详解

    JWT白名单允许特定JWT直接通过验证无需重复检查签名或过期时间适用于内部服务快速授权但存在安全风险。核心解决方案包括:1.验证前先检查JWT是否在白名单中若在则直接通过;2.白名单可存储于数据库缓存或配置文件;3.验证流程优先查白名单未命中则执行标准JWT验证;4.需提供接口管理白名单并定期清理过期项。主要安全风险包括JWT泄露后长期有效权限过大及管理难度增加。为安全使用应限制场景缩短有效期控制权限加强管理使用jti标识并结合其他安全措施。替代方案有刷新令牌Session机制OAuth2.0和ACL。白

    比较JWT、Session、SSO和OAuth2.0:场景应用与优劣势分析
    比较JWT、Session、SSO和OAuth2.0:场景应用与优劣势分析

    在现代Web应用及分布式系统中,身份认证与授权是保障系统安全性的关键环节。JWT(JSONWebTokens)、Session、SSO(SingleSign-On,单点登录)和OAuth2.0是四种常见的身份认证与授权机制,它们各自有不同的应用场景、优缺点。本文将对这四种机制进行对比分析,以便读者能够更好地理解和选择适合自身业务需求的认证授权方案。一、JWT(JSONWebTokens)JWT是一种在双方之间安全传输信息的开放标准(RFC7519)。这些信息可以被验证和信任,因为它们经过数字签名。JWT可

    springBoot项目常用目录有哪些
    springBoot项目常用目录有哪些

    springBoot项目常用目录springBoot项目的目录结构及名规范介绍基于SpringBoot开发时的目录结构及命名规范,通过介绍能够为你解决,在实际项目中如何规划目录结构?如何命名目录更规范?各个目录分别代表什么含义?等三个问题。目录说明servicex//项目名|-admin-ui//管理服务前端代码(一般将UI和SERVICE放到一个工程中,便于管理)|-servicex-auth//模块1|-servicex-common//模块2|-servicex-gateway//模块3|-serv

    Java API 开发中使用 JWT 鉴权
    Java API 开发中使用 JWT 鉴权

    随着互联网应用的广泛使用,安全性问题也逐渐成为重要的话题。为了保证应用的安全性,开发人员需要采取各种措施来防止未授权的访问和攻击。JWT(JSONWebToken)就是一种在网络应用中用于声明的一种安全传输方式。在JavaAPI开发中使用JWT鉴权,可以有效保护API的安全性,并且方便开发过程中的访问控制。JWT的基本概念JWT是由

    利用JWT在Go语言中实现身份验证的最佳实施方法
    利用JWT在Go语言中实现身份验证的最佳实施方法

    随着Web应用程序的普及和应用范围的扩大,保护用户数据和身份信息越来越重要。在应用程序中进行身份验证是非常必要的,本文将介绍在Go语言中如何使用JWT实现身份验证的最佳实践。什么是JWTJWT是JSONWebToken的缩写,是一种不需要Cookie等存储方式而能够安全传递信息的身份验证机制。一个JWT由三部分组成:Header:包含算法和类型等信息。P

    使用ThinkPHP6实现JWT认证的方法详情
    使用ThinkPHP6实现JWT认证的方法详情

    JWT(JSONWebToken)是一种轻量级的认证和授权机制,它使用JSON对象作为安全令牌,可以在多个系统之间安全地传输用户身份信息。而ThinkPHP6是一种基于PHP语言的高效、灵活的MVC框架,它提供了许多有用的工具和功能,其中就包括JWT认证机制。在本文中,我们将介绍如何使用ThinkPHP6进行JWT认证,以保障Web应用程序的安全性和可靠

    用Go语言实现简单而安全的用户认证,使用JWT
    用Go语言实现简单而安全的用户认证,使用JWT

    随着网络技术的快速发展,越来越多的网站和应用需要实现用户认证功能。但是,传统的用户名和密码认证方式存在安全风险,因为它们通常会被保存在数据库中,一旦数据库被攻击,就会导致用户信息泄露。为了解决这个问题,JWT(JSONWebToken)应运而生。JWT是一种开放标准(RFC7519),它定义了一种简单的、自包含的方式来传输信息,该信息可以被验证和信任。

    解析SpringBoot和SpringMVC之间的异同
    解析SpringBoot和SpringMVC之间的异同

    解析SpringBoot和SpringMVC之间的异同SpringBoot和SpringMVC是Java领域中非常重要的开发框架。虽然它们都属于Spring框架的一部分,但是在使用和功能上有一些明显的区别。本文将对SpringBoot和SpringMVC进行比较,解析它们之间的异同。首先,让我们来了解一下SpringBoot。SpringBo

    探索SpringCloud和SpringBoot在微服务领域的不同应用方式
    探索SpringCloud和SpringBoot在微服务领域的不同应用方式

    近年来,随着云计算和分布式架构的兴起,微服务架构的应用越来越广泛。而SpringCloud和SpringBoot作为Java开发中的两个重要框架,对于微服务的实现起到了重要的作用。然而,很多人对于它们在微服务领域的不同应用方式还存在一定的疑惑。本文将从不同的角度探索SpringCloud和SpringBoot在微服务中的应用方式。首先,我们来了解一下Spri

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。