千家信息网

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

发表于:2024-11-27 作者:千家信息网编辑
千家信息网最后更新 2024年11月27日,本文小编为大家详细介绍"Spring Boot怎么集成JWT实现前后端认证",内容详细,步骤清晰,细节处理妥当,希望这篇"Spring Boot怎么集成JWT实现前后端认证"文章能帮助大家解决疑惑,下
千家信息网最后更新 2024年11月27日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的数据结构

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{//创建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 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认证拦截器

 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("/**");    } }

登录验证流程

示例代码

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

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

认证 信息 数据 主题 时间 对象 用户 算法 服务 内容 字段 文章 服务器 加密 应用 登录 令牌 分布式 密钥 属性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全 西强我弱 北京软件开发公司哪家专业 网络技术维护合同 服务器主板品牌排行 创建网络安全密钥 恐龙岛显示没有服务器 石家庄纷腾网络技术有限公司 文明重启创建服务器要多少钱 自学网络技术书籍 科技图鉴互联网焦虑图鉴 软件开发工作要疯了怎么安慰 中国台湾oa软件开发需要多少钱 分布式软件开发模型 js能直接操作数据库吗 南京企业软件开发教程 在服务器中打开任务管理器 城乡网格化信息管理平台软件开发 怎样提高收银系统连接服务器 河北网络技术转让销售价格 云计算是对网络技术计算 滨州oa办公软件开发多少钱 微信发视频无法连接服务器怎么办 如何维护校园网络安全 网络安全法从颁布到实施的顺序 爱迪尔门锁数据库在哪个文件 计算机网络技术大一买电脑吗 用友软件开发商 网络安全保障体系和能力建设 xshell怎么暂停数据库 嘉定区互联网教育科技软件
0