广告
返回顶部
首页 > 资讯 > 精选 >Spring Boot怎么集成JWT实现前后端认证
  • 382
分享到

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

2023-06-30 01:06:08 382人浏览 八月长安
摘要

本文小编为大家详细介绍“spring Boot怎么集成Jwt实现前后端认证”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring Boot怎么集成JWT实现前后端认证”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢

本文小编为大家详细介绍“spring Boot怎么集成Jwt实现前后端认证”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring Boot怎么集成JWT实现前后端认证”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

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包

<dependency>        <groupId>io.jsonwebtoken</groupId>        <artifactId>jjwt</artifactId>        <version>0.9.1</version>  </dependency>

编写jwt工具

public class JwtUtil{//创建jwtpublic 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<Claims> pareseJWT(String jwt)    {        Jws<Claims> 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;    }  }         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认证拦截器

 Componentpublic 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;    }}

配置拦击器

@Configurationpublic 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<String, Object> 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;}

读到这里,这篇“Spring Boot怎么集成JWT实现前后端认证”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: Spring Boot怎么集成JWT实现前后端认证

本文链接: https://www.lsjlt.com/news/326979.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作