zoukankan      html  css  js  c++  java
  • JWT 理解

    概念:

    JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。

    优点是在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。
    缺点是无法作废已颁布的令牌/不易应对数据过期。

    JWT 只是一种规范,具体应用,还是需要开发人员自己实现取数据的过程。

    一般实现过程是这样的:

    1.用户登陆后生成jwt token。

    2.以后每次客户端访问在请求头或者cookie 中带上此cookie。

    3.服务端接收此token后,获取用户信息,获取用户上下文数据,用户编写代码获取自己相关的数据。

    JWT生成代码实现:

    1.编辑POM.xml文件,加入下面的片段

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

    2.JWT生成和解析过程。

    package com.neo.util;
    
    import java.util.Base64;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.util.StringUtils;
    
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.interfaces.Claim;
    import com.auth0.jwt.interfaces.DecodedJWT;
    
    public class JwtUtil {
        
        /**
         * 加密的密码,这个密码不能对外面泄漏。
         */
        public static final String SECRET = "JKKLJOoasdlfj";
        /** token 过期时间: 10天 */
        public static final int calendarField = Calendar.DATE;
        public static final int calendarInterval = 10;
    
        /**
         * JWT生成Token.<br/>
         * 
         * JWT构成: header, payload, signature
         * 
         * @param user_id 用户ID
         * @param name 用户名称
         * 
         * 这些参数可以扩展的注意不要放入敏感信息,比如密码。
         *            
         */
        public static String createToken(Long user_id,String name) throws Exception {
            Date iatDate = new Date();
            // expire time
            Calendar nowTime = Calendar.getInstance();
            nowTime.add(calendarField, calendarInterval);
            Date expiresDate = nowTime.getTime();
    
            // header Map
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("alg", "HS256");
            map.put("typ", "JWT");
    
            // build token
            // param backups {iss:Service, aud:APP}
            String token = JWT.create().withHeader(map) // header
                    .withClaim("iss", "Service") // payload
                    .withClaim("aud", "APP")
                    .withClaim("user_id", null == user_id ? null : user_id.toString())
                    .withClaim("name", name)
                    .withIssuedAt(iatDate) // sign time
                    .withExpiresAt(expiresDate) // expire time
                    .sign(Algorithm.HMAC256(SECRET)); // signature
    
            return token;
        }
    
        /**
         * 解密Token
         * 
         * @param token
         * @return
         * @throws Exception
         */
        public static Map<String, Claim> verifyToken(String token) {
            DecodedJWT jwt = null;
            try {
                JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
                jwt = verifier.verify(token);
            } catch (Exception e) {
                // e.printStackTrace();
                // token 校验失败, 抛出Token验证非法异常
            }
            return jwt.getClaims();
        }
    
        /**
         * 根据Token获取user_id
         * 
         * @param token
         * @return user_id
         */
        public static Long getAppUID(String token) {
            Map<String, Claim> claims = verifyToken(token);
            Claim user_id_claim = claims.get("user_id");
            if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {
                // token 校验失败, 抛出Token验证非法异常
            }
            return Long.valueOf(user_id_claim.asString());
        }
        
        public static void main(String[] args) throws Exception {
            String token=createToken(9999L,"ray");
            System.out.println(token);
            Long uid=getAppUID(token);
            Map<String, Claim> claims = verifyToken(token);
            System.out.println(claims.get("name").asString());
            //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJBUFAiLCJ1c2VyX2lkIjoiOTk5OSIsImlzcyI6IlNlcnZpY2UiLCJuYW1lIjoiemhhbmd5ZyIsImV4cCI6MTU0MTk0NzA4MSwiaWF0IjoxNTQxMDgzMDgxfQ.fUc0PSjdvR5ihHUv8hk7eQeUlv5RkmrsCZxq6bUXYDc
             
    
           byte[] bytes=    Base64.getUrlDecoder().decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
           System.out.println(new String(bytes));
           
           bytes=    Base64.getUrlDecoder().decode("eyJhdWQiOiJBUFAiLCJ1c2VyX2lkIjoiOTk5OSIsImlzcyI6IlNlcnZpY2UiLCJuYW1lIjoiemhhbmd5ZyIsImV4cCI6MTU0MTk0NzA4MSwiaWF0IjoxNTQxMDgzMDgxfQ");
           System.out.println(new String(bytes));
        }
    
    
    }

    需要注意的是,我们可以在token放入用户ID,用户名称等信息,不要放入权限密码等信息,因为TOKEN 会在有效期内不发生变化,另外头部和payload信息是base64编码,是可以被解码的。

  • 相关阅读:
    CentOS内核优化提示:cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: 没有那个文件或目录
    CentOS 7使用通过二进制包安装MySQL 5.7.18
    MySQL错误:TIMESTAMP with implicit DEFAULT value is deprecated
    CentOS增加用户到sudo用户组
    Linux下Shell函数返回值实现种类
    Nginx配置直接php
    Nginx报Primary script unknown的错误解决
    CentOS下的apache配置支持php
    CentOS 7解压安装PHP5.6.13
    [ASP.NET MVC] 利用自定义的AuthenticationFilter实现Basic认证
  • 原文地址:https://www.cnblogs.com/yg_zhang/p/9913680.html
Copyright © 2011-2022 走看看