传统的资源服务授权流程如下:

  1. 客户端先去授权服务器申请令牌,申请令牌后,携带令牌访问资源服务器;
  2. 资源服务器访问授权服务器校验令牌的合法性;
  3. 如果校验成功,授权服务器返回用户信息给资源服务器;
  4. 资源服务器接收到校验成功的结果后,返回客户端请求的资源。

传统授权方法的问题是用户每次请求资源服务,资源服务都需要携带令牌访问认证服务去校验令牌的合法性,并根据令牌获取用户的相关信息,性能低下。

为了避免每次资源服务器反复校验令牌的合法性,我们可以利用公钥私钥完成对令牌的加密和解密。公钥私钥授权流程如下:

  1. 客户端请求认证服务器申请令牌;
  2. 认证服务器采用非对称加密算法,使用私钥生成令牌;
  3. 客户端携带令牌访问资源服务客户端,即在Http header中添加Authorization:Bearer令牌;
  4. 资源服务器使用公钥校验令牌是否有效;
  5. 令牌有效,资源服务器向客户端响应资源信息。

实际上,认证服务器生成一对公钥和私钥,私钥留给自己,公钥发给其他资源服务器。在发放令牌时,先利用MD5之类的摘要算法生成令牌摘要,并通过私钥对改摘要进行签名(加密)。当客户端携带令牌访问资源时,取下签名,即利用公钥进行解密得到令牌的摘要。再通过采用MD5算法生成令牌摘要,最后,判断两个摘要是否相同,若相同,则令牌有效,否则,令牌无效。

1. 生成公钥私钥

生成密钥证书

使用JDK自带工具keytool生成ssl证书:

keytool -genkeypair -alias changgou -keypass changgou -keyalg RSA -keypass changgou -storepass changgou -keystore C:/Users/Administrator/Desktop/changgou.jks

导出公钥

这里参考大佬的实现

import sun.misc.BASE64Encoder;import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.security.*;
import java.security.cert.Certificate;/*** 从证书中导出公钥私钥*/
public class ExportCert {//导出证书 base64格式public static void exportCert(KeyStore keystore, String alias, String exportFile) throws Exception {Certificate cert = keystore.getCertificate(alias);BASE64Encoder encoder = new BASE64Encoder();String encoded = encoder.encode(cert.getEncoded());FileWriter fw = new FileWriter(exportFile);fw.write("-----BEGIN CERTIFICATE-----");fw.write(encoded);fw.write("-----END CERTIFICATE-----");fw.close();}//得到KeyPairpublic static KeyPair getKeyPair(KeyStore keystore, String alias, char[] password) {try {Key key = keystore.getKey(alias, password);if (key instanceof PrivateKey) {Certificate cert = keystore.getCertificate(alias);PublicKey publicKey = cert.getPublicKey();return new KeyPair(publicKey, (PrivateKey) key);}} catch (UnrecoverableKeyException e) {} catch (NoSuchAlgorithmException e) {} catch (KeyStoreException e) {}return null;}//导出私钥public static void exportPrivateKey(PrivateKey privateKey,String exportFile) throws Exception {BASE64Encoder encoder = new BASE64Encoder();String encoded = encoder.encode(privateKey.getEncoded());FileWriter fw = new FileWriter(exportFile);fw.write("-----BEGIN PRIVATE KEY-----");fw.write(encoded);fw.write("-----END PRIVATE KEY-----");fw.close();}//导出公钥public static void exportPublicKey(PublicKey publicKey,String exportFile) throws Exception {BASE64Encoder encoder = new BASE64Encoder();String encoded = encoder.encode(publicKey.getEncoded());FileWriter fw = new FileWriter(exportFile);fw.write("-----BEGIN PUBLIC KEY-----"); fw.write(encoded);fw.write("-----END PUBLIC KEY-----");fw.close();}public static void main(String args[]) throws Exception {String keyStoreType = "JKS";String keystoreFile = "C:/Users/Administrator/Desktop/changgou.jks";String password = "changgou";String alias = "changgou";KeyStore keystore = KeyStore.getInstance(keyStoreType);keystore.load(new FileInputStream(new File(keystoreFile)), password.toCharArray());String exportCertFile = "C:/Users/Administrator/Desktop/cms.cer";String exportPrivateFile = "C:/Users/Administrator/Desktop/cmsPrivateKey.txt";String exportPublicFile = "C:/Users/Administrator/Desktop/cmsPublicKey.txt";ExportCert.exportCert(keystore, alias, exportCertFile);KeyPair keyPair = ExportCert.getKeyPair(keystore, alias, password.toCharArray());ExportCert.exportPrivateKey(keyPair.getPrivate(), exportPrivateFile);ExportCert.exportPublicKey(keyPair.getPublic(), exportPublicFile);System.out.println("OK");}
}

2. 生成令牌

JWT签名算法中,常采用的两种加密算法:

  • HS256;
  • RS256。

签名实际上是一个加密的过程,生成一段标识(也是JWT的一部分)作为接收方验证信息是否被篡改的依据。

RS256 (采用SHA-256 的 RSA 签名) 是一种非对称算法, 它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。

另一方面, HS256 (带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。

在开发应用的时候启用JWT,使用RS256更加安全,你可以控制谁能使用什么类型的密钥。生成令牌的实现:

    /*** 利用私钥创建jwt令牌*/@Testpublic void testGenerateRSAJwt() {// 加载证书ClassPathResource resource = new ClassPathResource("changgou.jks");// 读取证书KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource, "changgou".toCharArray());// 获取私钥KeyPair keyPair = keyStoreKeyFactory.getKeyPair("changgou", "changgou".toCharArray());RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();// 创建令牌,使用RSA算法进行加盐加密Map<String, Object> payload = new HashMap<>();payload.put("name", "jack");payload.put("age", 24);Jwt jwt = JwtHelper.encode(JSON.toJSONString(payload), new RsaSigner(privateKey));System.out.println(jwt.getEncoded());}

3. 解析令牌

利用公钥解析Jwt令牌。

    /*** 利用公钥解析jwt令牌*/@Testpublic void testCheckRSAJwt(){String jwtStr = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiamFjayIsImFnZSI6MjR9.UTt8SEfzL3T7Xr_zj2ipWdt_ROiw2QOahJVAc5qSEb1keNAGcnKOu2Z-_Oe1kD1fZFIY3Y17QVGIjqONFa54BkXmeb2d6Hfq6pW2lD3ht_1iyVdZ2FPkDHVzyYMvUMgH1V85hJagUsGK0NyWBVIaODUj83Kpdky2DsXqUmkCrNQu03g-kKV3LLQ514EPpkcjAo2CrxbFHhQjOpPjQAd2C_FdJllVnQBgXD8z-h1VBOkhe1N3QH8AZx9PnKZMLEtKsN6U5cSbbj0vf5DKaYiyf5P_5DJ_OdkRcd5XvTZjGmFZA8FL5IYOtax4-ILPbdaMsYh2CYDct2n02crxpThkjw";String publicKey = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFsEiaLvij9C1Mz+oyAmt47whAaRkRu/8kePM+X8760UGU0RMwGti6Z9y3LQ0RvK6I0brXmbGB/RsN38PVnhcP8ZfxGUH26kX0RK+tlrxcrG+HkPYOH4XPAL8Q1lu1n9x3tLcIPxq8ZZtuIyKYEmoLKyMsvTviG5flTpDprT25unWgE4md1kthRWXOnfWHATVY7Y/r4obiOL1mS5bEa/iNKotQNnvIAKtjBM4RlIDWMa6dmz+lHtLtqDD2LF1qwoiSIHI75LQZ/CNYaHCfZSxtOydpNKq8eb1/PGiLNolD4La2zf0/1dlcr5mkesV570NxRmU1tFm8Zd3MZlZmyv9QIDAQAB-----END PUBLIC KEY-----";Jwt jwt = JwtHelper.decodeAndVerify(jwtStr, new RsaVerifier(publicKey));System.out.println(jwt.getClaims());}

OAuth2.0公钥私钥授权技术相关推荐

  1. OAuth2.0 - 自定义模式授权 - 短信验证码登录

    一.OAuth2.0 - 自定义模式授权 上篇文章我们分析了目前的情况,演示了微服务的大环境下在保证安全的情况下通过SpringGateWay实现统一的鉴权处理,但是前面的演示中,我们都是基于用户名密 ...

  2. 前后端分离Oauth2.0 - springsecurity + spring-authorization-server —授权码模式

    序言 对于目前有很多的公司在对旧的web工程做重构,拆分服务,使用前端vue,后端springboot微服务,重构的要点之一是认证授权框架的选型. 对于原有的 spring-security-oaut ...

  3. OAuth2.0协议(一) - 授权码许可流程

    OAuth2.0是什么可以拿来做什么,它只认真的做了一件事授权(Authorization).OAuth2.0是 Open Authorization 2.0的简称,既然是2.0那前面肯定有个1.0. ...

  4. 使用Oauth2.0实现微博授权登录

    本文章参考资料: http://blog.csdn.net/highboys/article/details/52139268 http://blog.csdn.net/yypsober/articl ...

  5. 从零开始超详细的Spring Security OAuth2.0实现分布式系统授权(注册中心+网关+认证授权服务(JWT令牌验证)+资源调用服务)

    文章目录 一.OAuth2.0 1.介绍 2.例子 3.执行流程 二.Spring Cloud Security OAuth2 1.环境介绍 2.认证流程 三.整合分布式项目 1.技术方案 2.项目结 ...

  6. OAuth2.0认证和授权原理

     什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和 ...

  7. 图文并茂,带你梳理一下 OAuth2.0 概念和授权流程机制

    作者:Hellxz's Blog cnblogs.com/hellxz/p/oauth2_process.html 阅读目录 OAuth2 的概念 OAuth2授权模式 授权码模式(Authoriza ...

  8. OAuth2.0认证服务器之授权码存放

    第一种方式:采用"内存"存取授权码,即我们在认证服务器的配置类(AuthorizationServerConfigurerAdapter的继承类)中做下述修改: import or ...

  9. 基于ThinkPHP3.2.3的微信OAuth2.0微信网页授权

    为了让大家不用重复造轮子,我写了一个TP控制器,继承控制器就可以直接用微信网页授权功能,但对于不是使用TP的小伙伴,可以直接在./Application/Home/Common/function.ph ...

  10. android新浪微博oauth2.0,新浪微博 Android SDK中OAuth2.0隐式授权部分的一个代码逻辑问题...

    在最近使用新浪微博android sdk开发微博登录的时候,从日志中发现一个问题,就是自定义的WeiboDialogListener里面的方法,比如onComplete或者onCancel等,经常会被 ...

最新文章

  1. shell的数字、字符串处理
  2. Servlet笔记1
  3. 接口文件也是.java结尾吗
  4. 硬核艿艿,新鲜出炉,直接带你弄懂 Spring Boot Jar 启动原理!
  5. 我的世界一进去就java_我的世界国际java版1.12.2加了光影修复进游戏就直接崩溃...
  6. python论坛签到_论坛自动签到教程
  7. 工作积累(五)——使用spring@Value注解实现常量功能
  8. SAP Spartacus HTTP请求url里的语言和货币参数是如何加上去的
  9. oracle nls_lang gbk,Oracle客户端NLS_LANG参数的设置详解
  10. JVM学习-分代收集算法
  11. corn表达式的简单使用
  12. phpstorm的安装和破解
  13. 《麦肯锡方法》读书笔记4
  14. 看完浪曦相关视频后的感受
  15. html文本框虚线并加上文字,文字边框虚线样式用css怎么写?(示例)
  16. 局部替换算法最小生成树
  17. 十一新疆之旅中邂逅的一首诗《黄河,母亲之河》
  18. 苹果手机在未激活的状况下待机时间长了会自动关机吗
  19. 随机梯度下降与梯度下降的区别?
  20. 《孙悟空大战白骨精》小游戏

热门文章

  1. CodeForce-476D-Dreamoon and Sets
  2. Spring Boot基础学习笔记08
  3. 栈的图文解析 和 对应3种语言的实现(C/C++/Java)
  4. 一、恒生电子面试 (校招)
  5. 操作系统的作用及类别
  6. Fake Location(安卓)
  7. cad计算机配置要求,CAD对电脑硬件的配置要求
  8. 数字图像处理,相位相关图像配准算法的C++实现
  9. 智能电导率系统电路设计详解
  10. 如何拆分PDF文件,PDF如何拆分页面