JWT和OAuth2在SpringBoot下的实现

JWT和OAuth2在SpringBoot下的实现

JWT

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
什么时候你应该用JSON Web Tokens
下列场景中使用JSON Web Token是很有用的:
Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWTs可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:

Header
Payload
Signature

因此,一个典型的JWT看起来是这个样子的:

xxxxx.yyyyy.zzzzz

关于JWT更详尽的解释

JWT生成和验证示例

引入依赖

    // https://mvnrepository.com/artifact/com.auth0/java-jwt
    compile group: 'com.auth0', name: 'java-jwt', version: '3.8.2'

码代码

    /**
     * 生成Token,携带自定义信息
     */
    @Test
    public void createTokenWithChineseClaim() {

        Date nowDate = new Date();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        Date date = calendar.getTime();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        System.out.println(simpleDateFormat.format(date));

        calendar.set(Calendar.MINUTE , calendar.get(Calendar.MINUTE)+6);

        System.out.println(simpleDateFormat.format(calendar.getTime()) );

//        Date expireDate = getAfterDate(nowDate, 0, 0, 0, 2, 0, 0);// 2小过期
        Date expireDate = calendar.getTime();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        Algorithm algorithm = Algorithm.HMAC256("secret");
        String token = JWT.create().withHeader(map)
                /* 设置 载荷 Payload */
                .withClaim("loginName", "zhuoqianmingyue").withClaim("userName", "张三").withClaim("deptName", "技术部")
                .withIssuer("SERVICE")// 签名是有谁生成 例如 服务器
                .withSubject("this is test token")// 签名的主题
                // .withNotBefore(new Date())//定义在什么时间之前,该jwt都是不可用的
                .withAudience("APP")// 签名的观众 也可以理解谁接受签名的
                .withIssuedAt(nowDate) // 生成签名的时间
                .withExpiresAt(expireDate)// 签名过期的时间
                /* 签名 Signature */
                .sign(algorithm);

        Assert.assertTrue(token.length() > 0);

        System.out.println(token);
//        return token;
    }

    /**
     * 验证token
     * @throws UnsupportedEncodingException
     */
    @Test
    public void verifyToken() throws UnsupportedEncodingException {
        String token = createTokenWithChineseClaimProc();

        Algorithm algorithm = Algorithm.HMAC256("secret");
        JWTVerifier verifier = JWT.require(algorithm).withIssuer("SERVICE").build(); // Reusable verifier instance
        DecodedJWT jwt = verifier.verify(token);

        String subject = jwt.getSubject();
        List<String> audience = jwt.getAudience();
        Map<String, Claim> claims = jwt.getClaims();
        for (Map.Entry<String, Claim> entry : claims.entrySet()) {
            String key = entry.getKey();
            Claim claim = entry.getValue();
//            log.info("key:" + key + " value:" + claim.asString());
            System.out.println("key:" + key + " value:" + claim.asString());
        }
        Claim claim = claims.get("loginName");

        System.out.println(claim.asString());
        System.out.println(subject);
        System.out.println(audience.get(0));

    }

    /**
     * 生成Token,携带自定义数据,返回Token
     * @return
     */
    public String createTokenWithChineseClaimProc() {

        Date nowDate = new Date();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        Date date = calendar.getTime();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        System.out.println(simpleDateFormat.format(date));

        calendar.set(Calendar.MINUTE , calendar.get(Calendar.MINUTE)+6);



        System.out.println(simpleDateFormat.format(calendar.getTime()) );

//        Date expireDate = getAfterDate(nowDate, 0, 0, 0, 2, 0, 0);// 2小过期
        Date expireDate = calendar.getTime();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        Algorithm algorithm = Algorithm.HMAC256("secret");
        String token = JWT.create().withHeader(map)
                /* 设置 载荷 Payload */
                .withClaim("loginName", "zhuoqianmingyue").withClaim("userName", "张三").withClaim("deptName", "技术部")
                .withIssuer("SERVICE")// 签名是有谁生成 例如 服务器
                .withSubject("this is test token")// 签名的主题
                // .withNotBefore(new Date())//定义在什么时间之前,该jwt都是不可用的
                .withAudience("APP")// 签名的观众 也可以理解谁接受签名的
                .withIssuedAt(nowDate) // 生成签名的时间
                .withExpiresAt(expireDate)// 签名过期的时间
                /* 签名 Signature */
                .sign(algorithm);

        Assert.assertTrue(token.length() > 0);

        System.out.println(token);
        return token;
    }

输出结果

2019-10-22 09:47:24
2019-10-22 09:53:24
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXB0TmFtZSI6IuaKgOacr-mDqCIsInN1YiI6InRoaXMgaXMgdGVzdCB0b2tlbiIsImF1ZCI6IkFQUCIsImxvZ2luTmFtZSI6InpodW9xaWFubWluZ3l1ZSIsImlzcyI6IlNFUlZJQ0UiLCJ1c2VyTmFtZSI6IuW8oOS4iSIsImV4cCI6MTU3MTc1MjQwNCwiaWF0IjoxNTY5MTYwMDQ0fQ.RAL4-5px0-49PXDf0u8arg0j3bo_L6ocU0Y9Alxf8sg
key:deptName value:技术部
key:sub value:this is test token
key:aud value:APP
key:loginName value:zhuoqianmingyue
key:iss value:SERVICE
key:userName value:张三
key:exp value:null
key:iat value:null
zhuoqianmingyue
this is test token
APP

OAuth2

OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 2.0(即完全废止了OAuth1.0)。 OAuth 2.0关注客户端开发者的简易性。要么通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户,要么允许第三方应用代表用户获得访问的权限。同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。

认证授权过程

在认证和授权的过程中涉及的三方包括:
1、服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表。
2、用户,存放在服务提供方的受保护的资源的拥有者。
3、客户端,要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识。

使用OAuth进行认证和授权的过程如下所示:
用户想操作存放在服务提供方的资源。
用户登录客户端向服务提供方请求一个临时令牌。
服务提供方验证客户端的身份后,授予一个临时令牌。
客户端获得临时令牌后,将用户引导至服务提供方的授权页面请求用户授权。在这个过程中将临时令牌 和客户端的回调连接发送给服务提供方。
用户在服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。
授权成功后,服务提供方引导用户返回客户端的网页。
客户端根据临时令牌从服务提供方那里获取访问令牌。
服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌。
客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。

OAuth2介绍
更详细的OAuth2原理、工作流程。

发布了48 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wangxudongx/article/details/101174313