@@ -612,25 +612,243 @@ WebLog框架
612612
613613![ 1584670695488] ( 微服务.assets/1584670695488.png )
614614
615+ ## 分布式认证
615616
617+ 加盐加密、token auth机制、jwt
616618
619+ ### 加盐加密
617620
621+ md5本身不可逆,但是唯一。
618622
623+ abc -> aaaaaaaaaaaaaaaa
619624
625+ qw -> bbbbb
620626
627+ 123456 -> cccccccccc
621628
622629
623630
631+ md5(123456 ) --- cccccccccccc
624632
633+ md5(1111111 ) ---ddddddd
625634
635+ md5(8888888) -----eeeeeeeeeee
626636
637+ md5的密码是唯一的,因此如果有人 将常见密码 做成了一张映射表,那么可能通过此映射表 查出明文 。
627638
639+ 如何解决? 加盐加密: 给原有密码中 参入一些 ”盐“,因为每个人的盐不同,所以加密的结果不同。
628640
641+ md5(11Q11Q111 ) ---ddasdfasddasdsdfddd
629642
630643
631644
632645
633646
647+ ### Token Auth
648+
649+ 分布式认证机制
650+
651+
652+
653+ 无状态
654+
655+ ![ 1593396108936] ( 微服务.assets/1593396108936.png )
656+
657+ 跨域:如果两个服务的IP、端口或者协议(http https ftp)不同,那么二者在相互访问时,必须先支持跨域 之后才能访问。
658+
659+ 介质问题:并不是所有的设备 都支持cookie (比如 移动设备就不支持 cookie)
660+
661+
662+
663+ Token Auth就是支持 无状态、跨域、并且能解决介质问题的 分布式认证机制。
664+
665+ Token Auth可以将数据存储cookie、LocalStorage、SessionStorage
666+
667+ Token Auth机制:
668+
669+ ![ 1593397546121] ( 微服务.assets/1593397546121.png )
670+
671+ token auth是一种机制,而jwt是它的一个具体的实现方案。
672+
673+ ### jwt
674+
675+ Json Web Token
676+
677+ jwt的组成结构: Header、PayLoad 、Signature三部分组成
678+
679+ token : header.payloder.signature
680+
681+
682+
683+
684+
685+ - Header: 头部,存放 token类型、加密算法 ,并将二者通过Base64 URL算法转为字符串形式保存。
686+
687+ ![ 1593398128729] ( 微服务.assets/1593398128729.png )
688+
689+ - PayLoad: 载荷,存放数据, 包含了以下3个模块快
690+
691+ - 基本声明: Token签发者信息、签发时间、过期时间
692+ - 公有声明: 一些业务相关的信息
693+ - 私有声明: 开发者信息
694+
695+ PayLoad最终仍然会将 以上三者通过Base64 UR.L加密成 字符串2。
696+
697+ Base64 URL算法本身是对称的(可逆),因此 不论是 公有、私有的等,都不安全。
698+
699+ - Signature:签名,用于防止用户进行一些不合法的校验。包含4部分:
700+
701+ - 使用Base64 URL算法加密后的 Header值
702+
703+ - .
704+
705+ - 使用Base64 URL算法加密后的 PayLoad值
706+
707+ - 盐secret
708+
709+ 还要注意,以上4部分:前三者连接起来,最后一个是独立存在的。
710+
711+ Signature最终会通过Header中设置的加密算法 将以上4部分进行整体加密。
712+
713+ 举例,假设算法是HS256,则签名就是以下:
714+
715+ HS256( Base64URL(Header)+"."+Base64URL(PayLoad) , secret )
716+
717+
718+
719+ 实现一个 jwt分布式认证的案例。
720+
721+ 基础版
722+
723+ 引入依赖
724+
725+ ``` xml
726+ <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
727+ <dependency >
728+ <groupId >io.jsonwebtoken</groupId >
729+ <artifactId >jwt</artifactId >
730+ <version >0.9.1</version >
731+ </dependency >
732+
733+ ```
734+
735+ 服务端
736+
737+ 流程:客户端——>服务端->服务端产生token ->将token返回给客户端->客户端拿着token去访问
738+
739+ ``` java
740+ import io.jsonwebtoken.Claims ;
741+ import io.jsonwebtoken.Jwts ;
742+ import io.jsonwebtoken.SignatureAlgorithm ;
743+ import io.jsonwebtoken.impl.DefaultClaims ;
744+
745+ import javax.crypto.spec.SecretKeySpec ;
746+ import javax.xml.bind.DatatypeConverter ;
747+ import java.util.Date ;
748+ import java.util.HashMap ;
749+ import java.util.Map ;
750+
751+ /*
752+ * Created by 颜群
753+ */
754+ public class JWTServer {
755+ // 1.服务端产生token
756+ public static void createToken (){
757+ // 1.Header
758+
759+ Map<String ,Object > header = new HashMap<> ();
760+ // 类型
761+ header. put(" typ" ," jwt" );
762+ // 加密算法
763+ header. put(" alg" ," HS256" );
764+
765+
766+ // 2.PayLoad (Map Claims)
767+ Claims claims = new DefaultClaims () ;
768+ claims. setId(" microservice" )
769+ .setSubject(" 微服务项目" )
770+ .setIssuedAt(new Date () )// 签发时间
771+ .setExpiration(new Date ( System . currentTimeMillis() + 1800 * 1000 ) )// 有效时间 (半小时内有效)
772+ .setAudience(" 自定义声明信息" ) ;
773+
774+ // 3.Signature
775+
776+ // 盐
777+ String salt = " yanqun" ;
778+ byte [] saltBase64 = DatatypeConverter . parseBase64Binary(salt) ;
779+
780+ SignatureAlgorithm hs256 = SignatureAlgorithm . HS256 ;
781+
782+ SecretKeySpec secretKey = new SecretKeySpec (saltBase64,hs256. getJcaName()) ;
783+
784+
785+ // 生成token
786+
787+ String token = Jwts . builder(). setHeader(header). setClaims(claims). signWith(hs256, secretKey). compact();
788+ System . out. println(" 服务端生成token:" + token);
789+
790+ }
791+
792+ public static void main (String [] args ) {
793+ createToken();
794+ }
795+ }
796+
797+ ```
798+
799+ 客户端
800+
801+ ``` java
802+ import io.jsonwebtoken.Claims ;
803+ import io.jsonwebtoken.Jws ;
804+ import io.jsonwebtoken.Jwts ;
805+
806+ /*
807+ * Created by 颜群
808+ */
809+ public class JWTClient {
810+
811+ // 客户端 携带token访问服务端
812+ // token + 盐
813+
814+ public static void visitServer (){
815+ String token = " eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJtaWNyb3NlcnZpY2UiLCJzdWIiOiLlvq7mnI3liqHpobnnm64iLCJpYXQiOjE1OTM0MDA1NTIsImV4cCI6MTU5MzQwMjM1MiwiYXVkIjoi6Ieq5a6a5LmJ5aOw5piO5L-h5oGvIn0.wo3KfQ60D2whdwMdMZjemRXz5m3ScuJsfjILV5p7RQ4" ;
816+ String salt = " yanqun" ;
817+
818+ // 获取jsw对象,jws就包含了所有的服务端校验信息
819+ Jws<Claims > jws = Jwts . parser(). setSigningKey(salt). parseClaimsJws(token);
820+ System . out. println(jws);
821+
822+ Claims claims = jws. getBody();
823+ System . out. println(" header:" + jws. getHeader());
824+ System . out. println(" payload:" + claims. getId());
825+ System . out. println(" payload:" + claims. getSubject());
826+ System . out. println(" payload:" + claims. getIssuedAt());
827+ System . out. println(" payload:" + claims. getExpiration());
828+ System . out. println(" payload:" + claims. getAudience());
829+
830+ System . out. println(" signature:" + jws. getSignature());
831+
832+
833+
834+ System . out. println(jws. getSignature(). equals(token. split(" \\ ." )[2 ]));
835+
836+
837+
838+
839+ }
840+
841+ public static void main (String [] args ) {
842+ visitServer();
843+ }
844+
845+ }
846+
847+ ```
848+
849+
850+
851+
634852
635853
636854
0 commit comments