江苏路街道网站建设,wordpress游客看小图登陆查看大图,手机wap网站怎样从微信公众号打开,网页模板免费网址Oauth2认证
Oauth2简介
简介
第三方认证技术方案最主要是解决认证协议的通用标准问题#xff0c;因为要实现跨系统认证#xff0c;各系统之间要遵循一定的接口协议。
OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时#xff0c;任何第三方都可以使…Oauth2认证
Oauth2简介
简介
第三方认证技术方案最主要是解决认证协议的通用标准问题因为要实现跨系统认证各系统之间要遵循一定的接口协议。
OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时任何第三方都可以使用OAUTH认证服务任何服务提供商都可以实现自身的OAUTH认证服务因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP、JavaScriptJavaRuby等各种语言开发包大大节约了程序员的时间因而OAUTH是简易的。互联网很多服务如Open API很多大公司如GoogleYahooMicrosoft等都提供了OAUTH认证服务这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。
Oauth协议目前发展到2.0版本1.0版本过于复杂2.0版本已得到广泛应用。
参考https://baike.baidu.com/item/oAuth/7153134?fraladdin
Oauth 协议https://tools.ietf.org/html/rfc6749
下边分析一个Oauth2认证的例子网站使用微信认证的过程 用户进入网站的登录页面点击微信的图标以微信账号登录系统用户是自己在微信里信息的资源拥有者。 点击“微信”出现一个二维码此时用户扫描二维码开始给网站授权。 资源拥有者同意给客户端授权 资源拥有者扫描二维码表示资源拥有者同意给客户端授权微信会对资源拥有者的身份进行验证验证通过后微信会询问用户是否给授权网站访问自己的微信数据用户点击“确认登录”表示同意授权微信认证服务器会颁发一个授权码并重定向到网站。 客户端获取到授权码请求认证服务器申请令牌 此过程用户看不到客户端应用程序请求认证服务器请求携带授权码。 认证服务器向客户端响应令牌 认证服务器验证了客户端请求的授权码如果合法则给客户端颁发令牌令牌是客户端访问资源的通行证。此交互过程用户看不到当客户端拿到令牌后用户在网站看到已经登录成功。 客户端请求资源服务器的资源 客户端携带令牌访问资源服务器的资源。网站携带令牌请求访问微信服务器获取用户的基本信息。 资源服务器返回受保护资源 资源服务器校验令牌的合法性如果合法则向用户响应资源信息内容。 注意资源服务器和认证服务器可以是一个服务也可以分开的服务如果是分开的服务资源服务器通常要请求认证服务器来校验令牌的合法性。
Oauth2.0认证流程如下 引自Oauth2.0协议rfc6749 https://tools.ietf.org/html/rfc6749
角色
客户端
本身不存储资源需要通过资源拥有者的授权去请求资源服务器的资源比如Android客户端、Web客户端浏览器端、微信客户端等。
资源拥有者
通常为用户也可以是应用程序即该资源的拥有者。
授权服务器也称认证服务器
用来对资源拥有的身份进行认证、对访问资源进行授权。客户端要想访问资源需要通过认证服务器由资源拥有者授权后方可访问。
资源服务器
存储资源的服务器比如网站用户管理服务器存储了网站用户信息网站相册服务器存储了用户的相册信息微信的资源服务存储了微信的用户信息等。客户端最终访问资源服务器获取资源信息。
常用术语
客户凭证(client Credentials)客户端的clientId和密码用于认证客户令牌(tokens)授权服务器在接收到客户请求后颁发的访问令牌作用域(scopes)客户请求访问令牌时由资源拥有者额外指定的细分权限(permission)
令牌类型
授权码仅用于授权码授权类型用于交换获取访问令牌和刷新令牌访问令牌用于代表一个用户或服务直接去访问受保护的资源刷新令牌用于去授权服务器获取一个刷新访问令牌BearerToken不管谁拿到Token都可以访问资源类似现金Proof of Possession(PoP) Token可以校验client是否对Token有明确的拥有权
特点
优点 更安全客户端不接触用户密码服务器端更易集中保护广泛传播并被持续采用短寿命和封装的token资源服务器和授权服务器解耦集中式授权简化客户端HTTP/JSON友好易于请求和传递token考虑多种客户端架构场景客户可以具有不同的信任级别缺点 协议框架太宽泛造成各种实现的兼容性和互操作性差不是一个认证协议本身并不能告诉你任何用户信息。Spring Security Oauth2授权码模式
创建项目导入依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-oauth2/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-security/artifactId/dependencydependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement3、编写实体类
package com.zuxia.entity;import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;/*** 用户类*/
public class User implements UserDetails {private String username;private String password;private ListGrantedAuthority authorities;Overridepublic Collection? extends GrantedAuthority getAuthorities() {return authorities;}Overridepublic String getPassword() {return password;}Overridepublic String getUsername() {return username;}Overridepublic boolean isAccountNonExpired() {return true;}Overridepublic boolean isAccountNonLocked() {return true;}Overridepublic boolean isCredentialsNonExpired() {return true;}Overridepublic boolean isEnabled() {return true;}
}
4.编写配置类 SecurityConfig.java
package com.zuxai.springsecurityoauth2demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*** Spring Security 配置类**/
Configuration
EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable()//关闭csrf.authorizeRequests()//授权.antMatchers(/oauth/**, /login/**, /logout/**).permitAll()//放行授权服务器端点.anyRequest().authenticated()//拦截所有的请求.and()//通过and()可以配置多个http.formLogin().permitAll();//放行所有的表单请求}
}5.编写自定义登录逻辑
UserService.java
package com.zuxia.springsecurityoauth2demo.service;import com.yjxxt.springsecurityoauth2demo.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;Service
public class UserService implements UserDetailsService {Autowiredprivate PasswordEncoder passwordEncoder;Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {String password passwordEncoder.encode(123456);return new User(admin,password, AuthorityUtils.commaSeparatedStringToAuthorityList(admin));}
}
6.授权服务器配置 AuthorizationServerConfig
package com.zuxia.springsecurityoauth2demo.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;/*** 授权服务器配置*/
Configuration
EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {Autowiredprivate PasswordEncoder passwordEncoder;Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception { //获取授权码//http://localhost:8080/oauth/authorizeresponse_typecodeclient_idadminredirect_urihttp://www.baidu.comscopeall clients.inMemory()//配置client_id.withClient(admin)//配置client-secret.secret(passwordEncoder.encode(112233))//配置redirect_uri用于授权成功后跳转.redirectUris(http://www.baidu.com)//配置申请的权限范围.scopes(all)//配置grant_type表示授权类型 authorization_code授权码模式.authorizedGrantTypes(authorization_code);}
}7.资源服务器配置 ResourceServerConfig.java
package com.zuxia.springsecurityoauth2demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;/*** 资源服务器配置 * 负责放行资源的路径*/
Configuration
EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//授权.anyRequest().authenticated()//都进行认证.and().requestMatchers().antMatchers(/user/**);//配置需要保护的资源路径}
}8.配置资源类
package com.zuxia.springsecurityoauth2demo.controller;import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/user)
public class UserController {GetMapping(/getCurrentUser)public Object getCurrentUser(Authentication authentication) {return authentication.getPrincipal();//返回当前登录用户的具体对象}
}9.测试 获取授权码 http://localhost:8080/oauth/authorize?response_typecodeclient_idadminredirect_urihttp://www.baidu.comscopeall
///oauth/authorize授权服务器的授权端点 //response_type返回类型 后面三个参数对应授权服务器配置中的配置
输入账户密码
点击授权获取授权码
根据授权码获取令牌POST请求
grant_type授权类型填写authorization_code表示授权码模式code授权码就是刚刚获取的授权码注意授权码只使用一次就无效了需要重新申请。client_id:客户端标识redirect_uri申请授权码时的跳转url一定和申请授权码时用的redirect_uri一致。scope:授权范围。
认证失败服务端返回 401 Unauthorized
注意此时无法请求到令牌访问服务器会报错
根据token去资源服务器拿资源
如果修改token就会报错
Spring Security Oauth2 密码模式
在上面的代码中进行适当的修改即可
SecurityConfig.java
package com.zuxia.springsecurityoauth2demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*** Spring Security 配置类**/
Configuration
EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//使用密码模式需要配置BeanOverridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers(/oauth/**, /login/**, /logout/**).permitAll().anyRequest().authenticated().and().formLogin().permitAll();}
}AuthorizationServerConfig.java
package com.zuxia.springsecurityoauth2demo.config;import com.yjxxt.springsecurityoauth2demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;/*** 授权服务器配置*/
Configuration
EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {Autowiredprivate PasswordEncoder passwordEncoder;Autowiredprivate AuthenticationManager authenticationManager;Autowiredprivate UserService userService;/*** 使用密码模式需要配置*/Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints//授权管理器.authenticationManager(authenticationManager)//自定义登录逻辑.userDetailsService(userService);}Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory()//配置client_id.withClient(admin)//配置client-secret.secret(passwordEncoder.encode(112233))//配置访问token的有效期.accessTokenValiditySeconds(3600)//配置刷新token的有效期.refreshTokenValiditySeconds(864000)//配置redirect_uri用于授权成功后跳转.redirectUris(http://www.baidu.com)//配置申请的权限范围.scopes(all)//配置grant_type表示授权类型.authorizedGrantTypes(authorization_code,password);}
}测试
在Redis中存储token
之前的代码我们将token直接存在内存中这在生产环境中是不合理的下面我们将其改造成存储在Redis中
1.添加依赖及配置
!--redis 依赖--
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependency
!-- commons-pool2 对象池依赖 --
dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId
/dependencyapplication.properties
# Redis配置
spring.redis.host192.168.10.100编写Redis配置类
RedisConfig.java
package com.zuxia.springsecurityoauth2demo.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;/*** 使用redis存储token的配置*/
Configuration
public class RedisConfig {Autowired//注入redis的连接工厂private RedisConnectionFactory redisConnectionFactory;Beanpublic TokenStore redisTokenStore(){return new RedisTokenStore(redisConnectionFactory);}}在认证服务器配置中指定令牌的存储策略为Redis
package com.zuxia.springsecurityoauth2demo.config;import com.yjxxt.springsecurityoauth2demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;/*** 授权服务器配置*/
Configuration
EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {Autowiredprivate PasswordEncoder passwordEncoder;Autowiredprivate AuthenticationManager authenticationManager;Autowiredprivate UserService userService;AutowiredQualifier(redisTokenStore)private TokenStore tokenStore;/*** 使用密码模式需要配置*/Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints//权限管理器.authenticationManager(authenticationManager)//自定义登录逻辑.userDetailsService(userService)//令牌存储位置.tokenStore(tokenStore);}Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory()//配置client_id.withClient(admin)//配置client-secret.secret(passwordEncoder.encode(112233))//配置访问token的有效期.accessTokenValiditySeconds(3600)//配置刷新token的有效期.refreshTokenValiditySeconds(864000)//配置redirect_uri用于授权成功后跳转.redirectUris(http://www.baidu.com)//配置申请的权限范围.scopes(all)//配置grant_type表示授权类型.authorizedGrantTypes(password);}
}测试
使用密码模式请求token
JWT
常见的认证机制
HTTP Basic Auth
HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password简言之Basic Auth是配合RESTful API 使用的最简单的认证方式只需提供用户名密码即可但由于有把用户名密码暴露给第三方客户端的风险在生产环境下被使用的越来越少。因此在开发对外开放的RESTful API时尽量避免采用HTTP Basic Auth。
Cookie Auth
Cookie认证机制就是为一次请求认证在服务端创建一个Session对象同时在客户端的浏览器端创建了一个Cookie对象通过客户端带上来Cookie对象来与服务器端的session对象匹配来实现状态管理的。默认的当我们关闭浏览器的时候cookie会被删除。但可以通过修改cookie 的expire time使cookie在一定时间内有效。
OAuth
OAuth开放授权,Open Authorization是一个开放的授权标准允许用户让第三方应用访问该用户在某一web服务上存储的私密的资源如照片视频联系人列表而无需将用户名和密码提供给第三方应用。如网站通过微信、微博登录等主要用于第三方登录。
OAuth允许用户提供一个令牌而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的第三方系统例如视频编辑网站)在特定的时段例如接下来的2小时内内访问特定的资源例如仅仅是某一相册中的视频。这样OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息而非所有内容。
下面是OAuth2.0的流程 这种基于OAuth的认证机制适用于个人消费者类的互联网产品如社交类APP等应用但是不太适合拥有自有认证权限管理的企业应用。
缺点过重。
Token Auth
使用基于 Token 的身份验证方法在服务端不需要存储用户的登录记录。大概的流程是这样的
客户端使用用户名跟密码请求登录服务端收到请求去验证用户名与密码验证成功后服务端会签发一个 Token再把这个 Token 发送给客户端客户端收到 Token 以后可以把它存储起来比如放在 Cookie 里客户端每次向服务端请求资源的时候需要带着服务端签发的 Token服务端收到请求然后去验证客户端请求里面带着的 Token如果验证成功就向客户端返回请求的数据 比第一种方式更安全比第二种方式更节约服务器资源比第三种方式更加轻量。
具体Token Auth的优点Token机制相对于Cookie机制又有什么好处呢
支持跨域访问: Cookie是不允许垮域访问的这一点对Token机制是不存在的前提是传输的用户认证信息通过HTTP头传输.无状态(也称服务端可扩展行):Token机制在服务端不需要存储session信息因为Token 自身包含了所有登录用户的信息只需要在客户端的cookie或本地介质存储状态信息.更适用CDN: 可以通过内容分发网络请求你服务端的所有资料如javascriptHTML,图片等而你的服务端只要提供API即可.去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成只要在你的API被调用的时候你可以进行Token生成调用即可.更适用于移动应用: 当你的客户端是一个原生平台iOS, AndroidWindows 10等时Cookie是不被支持的你需要通过Cookie容器进行处理这时采用Token认证机制就会简单得多。CSRF:因为不再依赖于Cookie所以你就不需要考虑对CSRF跨站请求伪造的防范。性能: 一次网络往返时间通过数据库查询session信息总比做一次HMACSHA256计算的Token验证和解析要费时得多.不需要为登录页面做特殊处理: 如果你使用Protractor 做功能测试的时候不再需要为登录页面做特殊处理.基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库.NET, Ruby, Java,Python, PHP和多家公司的支持如Firebase,Google, Microsoft.
JWT简介
什么是JWT
JSON Web TokenJWT是一个开放的行业标准RFC 7519它定义了一种简介的、自包含的协议格式用于在通信双方传递json对象传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名防止被篡改。
官网 https://jwt.io/
标准 https://tools.ietf.org/html/rfc7519
JWT令牌的优点
jwt基于json非常方便解析。可以在令牌中自定义丰富的内容易扩展。通过非对称加密算法及数字签名技术JWT防止篡改安全性高。资源服务使用JWT可不依赖认证服务即可完成授权。
缺点
JWT令牌较长占存储空间比较大。
JWT组成
一个JWT实际上就是一个字符串它由三部分组成头部、载荷与签名。
头部(Header)
头部用于描述关于该JWT的最基本的信息例如其类型即JWT以及签名所用的算法如HMAC SHA256或RSA等。这也可以被表示成一个JSON对象。
{alg: HS256,typ: JWT
}typ是类型。alg签名的算法这里使用的算法是HS256算法
我们对头部的json字符串进行BASE64编码网上有很多在线编码的网站编码后的字符串如下
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64所以每6个比特为一个单元对应某个可打印字符。三个字节有24个比特对应于4个Base64单元即3个字节需要用4个可打印字符来表示。JDK 中提供了非常方便的 BASE64Encoder和 BASE64Decoder用它们可以非常方便的完成基于 BASE64 的编码和解码。
负载(Payload)
第二部分是负载就是存放有效信息的地方。这个名字像是特指飞机上承载的货品这些有效信息包含三个部分 标准中注册的声明建议但不强制使用 iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: jwt的过期时间这个过期时间必须要大于签发时间 nbf: 定义在什么时间之前该jwt都是不可用的. iat: jwt的签发时间 jti: jwt的唯一身份标识主要用来作为一次性token,从而回避重放攻击。 公共的声明
公共的声明可以添加任何的信息一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息因为该部分在客户端可解密.
私有的声明
私有声明是提供者和消费者所共同定义的声明一般不建议存放敏感信息因为base64是对称解密的意味着该部分信息可以归类为明文信息。
这个指的就是自定义的claim。比如下面那个举例中的name都属于自定的claim。这些claim跟JWT标准规定的claim区别在于JWT规定的claimJWT的接收方在拿到JWT之后都知道怎么对这些标准的claim进行验证(还不知道是否能够验证)而private claims不会验证除非明确告诉接收方要对这些claim进行验证以及规则才行。
{sub: 1234567890,name: John Doe,iat: 1516239022
}其中sub是标准的声明name是自定义的声明公共的或私有的
然后将其进行base64编码得到Jwt的第二部分 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbWVzIiwiYWRtaW4iOnRydWV9 提示声明中不要放一些敏感信息。
签证、签名signature
jwt的第三部分是一个签证信息这个签证信息由三部分组成
header (base64后的)payload (base64后的)secret盐一定要保密
这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串然后通过header中声明的加密方式进行加盐secret组合加密然后就构成了jwt的第三部分
8HI-Lod0ncfVDnbKIPJJqLH998duF9DSDGkx3gRPNVI将这三部分用.连接成一个完整的字符串,构成了最终的jwt:
eyJhbGciOiJIUzI1NiIsInR9cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.8HI-Lod0ncfVDnbKIPJJqLH998duF9DSDGkx3gRPNVI 注意secret是保存在服务器端的jwt的签发生成也是在服务器端的secret就是用来进行jwt的签发和jwt的验证所以它就是你服务端的私钥在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。