大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全家桶1年46,售后保障稳定
一.客户端模式
客户端模式只对客户端进行授权,不涉及到用户信息。如果API需要提供到第三方应用,第三方应用自己做用户授权,不需要用到用户资源,就可以用客户端模式,只对客户端进行授权访问api资源。
1.添加客户端
new Client()
{
ClientId="apiClientCd", //客户端Id
ClientSecrets={new Secret("apiSecret".Sha256()) }, //客户端密码
AllowedGrantTypes=GrantTypes.ClientCredentials, //客户端授权类型
AllowedScopes={ "secretapi" } //允许访问的资源
}
二.密码模式
1.添加客户端
new Client()
{
ClientId="apiClientPassword", //客户端Id
ClientSecrets={new Secret("apiSecret".Sha256()) }, //客户端密码
AllowedGrantTypes=GrantTypes.ResourceOwnerPassword, //客户端授权类型
AllowedScopes={ "secretapi" } //允许访问的资源
}
三.隐藏模式
密码模式将用户的密码暴露给了客户端,隐藏模式可以解决这个问题,由用户自己在IdentityServer服务器进行登录验证,客户端不需要知道用户的密码。
1.隐藏模式传递参数
解析:根据OAuth2.0协议,隐藏模式需要传的参数如下所示:
client_id:客户端Id
redirect_uri=重定向Url,用户登录成功后跳回此地址
response_type=token,固定值,表示获取token
scope=secretapi,此token需要访问的api
[1]接受参数的地址则是IdentityServer的Discover文档中的authorization_endpoint节点
[2]把参数和地址拼接成以下地址:http://localhost:5000/connect/authorize?client_id=apiClientImpl&redirect_uri=https://localhost:5002/auth.html&response_type=token&scope=secretapi,直接访问会跳转到用户登录页面
2.添加客户端
new Client()
{
ClientId="apiClientImpl", //客户端Id
ClientName="ApiClient for Implicit",
AllowedGrantTypes=GrantTypes.Implicit, //客户端授权类型
RedirectUris = {"https://localhost:5002/auth.html" }, //允许登录后重定向的地址列表,可以有多个
AllowedScopes={ "secretapi" }, //允许访问的资源
AllowAccessTokensViaBrowser=true //允许将token通过浏览器传递
}
四.授权码模式
授权码模式和隐藏码模式最大不同是授权码模式不直接返回token,而是先返回一个授权码,然后再根据这个授权码去请求token。GrantTypes.Code表示授权码模式。
1.添加客户端
new Client()
{
ClientId="apiClientCode", //客户端Id
ClientName="ApiClient for Code", //客户端名称
ClientSecrets={new Secret("apiSecret".Sha256()) }, //客户端密码
AllowedGrantTypes=GrantTypes.Code, //客户端授权类型,Code:授权码模式
RedirectUris = {"https://localhost:5002/auth.html"}, //允许登录后重定向的地址列表,可以有多个
AllowedScopes={ "secretapi" } //允许访问的资源
}
2.授权码模式传递参数
client_id:客户端Id
redirect_uri=重定向Url,用户登录成功后跳回此地址
response_type=code,固定值,表示获取授权码
scope=secretapi,此token需要访问的api
[1]链接地址:http://localhost:5000/connect/authorize?client_id=apiClientCode&redirect_uri=https://localhost:5002/auth.html&response_type=code&scope=secretapi
[2]在浏览器中访问此链接,会跳转到用户登录界面,用之前创建的用户apiUser和密码登录后浏览器会自动跳转回设置的重定向链接
3.后端请求令牌
client_id:客户端Id
client_secret:客户端密码
grant_type:authorization_code,固定值
redirect_uri=重定向Url,用户登录成功后跳回此地址
code:获取到的授权码
scope=secretapi,此token需要访问的api
五.OAuth2.0原理
1.OAuth2.0四种授权方式
[1]GrantTypes.ClientCredentials为客户端凭证模式。适用于没有前端的命令行应用,即在命令行下请求令牌。这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
[2]GrantTypes.ResourceOwnerPassword为用户名密码模式。这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。
[3]GrantTypes.Implicit表示隐藏模式:允许直接向前端颁发令牌。只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间有效,浏览器关掉令牌就失效了。
[4]GrantTypes.Code表示授权码模式:指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
2.GitHub应用登记
解析:提交表单以后,GitHub应该会返回客户端ID和客户端密钥,这就是应用的身份识别码。
浏览器跳转GitHub的链接如下:
https://github.com/login/oauth/authorize?client_id=7e015d8ce32370079895&redirect_uri=http://localhost:8080/oauth/redirect
其中,client_id告诉GitHub谁在请求,redirect_uri是稍后跳转回来的网址。用户同意授权,GitHub就会跳转到redirect_uri指定的跳转网址,并且带上授权码:
http://localhost:8080/oauth/redirect?code=859310e7cecc9196f4af
后端使用这个授权码,向GitHub请求令牌:
const tokenResponse = await axios({
method: 'post',
url: 'https://github.com/login/oauth/access_token?' +
`client_id=${clientID}&` +
`client_secret=${clientSecret}&` +
`code=${requestToken}`,
headers: {
accept: 'application/json'
}
});
GitHub会返回一段JSON数据,里面包含了令牌accessToken:
const accessToken = tokenResponse.data.access_token;
根据令牌向API请求数据:
const result = await axios({
method: 'get',
url: `https://api.github.com/user`,
headers: {
accept: 'application/json',
Authorization: `token ${accessToken}`
}
});
六.OpenIdConnect
OpenIdConnect是OAuth2.0与OpenId的结合,之前所讲的token是用于访问授权的access_token,而id_token是用于身份验证的,作用完全不同。access_token是OAth2.0特性,而id_token是OpenIdConnect方案为改善OAuth2.0方案在身份验证方面的薄弱而加入的特性。OpenIdConnect支持的混合模式是基于隐藏模式与授权码模式的结合。
1.添加隐藏模式客户端
new Client()
{
ClientId="apiClientImpl", //客户端Id
ClientName="ApiClient for Implicit",
AllowedGrantTypes=GrantTypes.Implicit, //客户端授权类型,Implicit:隐藏模式
RedirectUris = {"https://localhost:5002/auth.html"}, //允许登录后重定向的地址列表,可以有多个
AllowedScopes={ "secretapi", IdentityServerConstants.StandardScopes.OpenId, "PhoneModel" }, //允许访问的资源
AllowAccessTokensViaBrowser=true, //允许将token通过浏览器传递
AlwaysIncludeUserClaimsInIdToken=true //允许ID_TOKEN附带Claims
}
2.添加混合模式客户端
new Client()
{
AlwaysIncludeUserClaimsInIdToken=true,
ClientId="apiClientHybrid", //客户端Id
ClientName="ApiClient for HyBrid",
ClientSecrets={new Secret("apiSecret".Sha256()) }, //客户端密码
AllowedGrantTypes=GrantTypes.Hybrid, //客户端授权类型,Hybrid:混合模式
RedirectUris = {"https://localhost:5002/auth.html"}, //允许登录后重定向的地址列表,可以有多个
AllowedScopes={ "secretapi", IdentityServerConstants.StandardScopes.OpenId, "PhoneModel" }, //允许访问的资源
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser=true
}
3.混合模式获取id_token
隐藏模式支持三种response_type:token、id_token、token id_token,分别用于请求access_token、id_token以及同时请求二者。而混合模式支持四种:code、code token、code id_token、code token id_token,可用于请求code、id_token、access_token以及同时请求三者。混合模式的请求链接如下所示:
http://localhost:5000/connect/authorize?client_id=apiClientHybrid&redirect_uri=https://localhost:5002/auth.html&response_type=code token id_token&scope=secretapi openid PhoneModel&nonce=123&response_mode=fragment
可以看到code,id_token,access_code都返回了。拿到code后可以根据code去获取access_token用 于访问被保护的api。也可以直接拿返回的acess_token用,直接返回的access_token由于是和隐藏模式一样以url参数带过来的,为安全考虑这个access_code的有效时间很段,默认是一个小时。
七.cookie、session、token、jwt、单点登录
1.典型的session登陆/验证流程
[1]浏览器登录发送账号密码,服务端查用户库,校验用户
[2]服务端把用户登录状态存为Session,生成一个sessionId
[3]通过登录接口返回,把sessionId set到cookie上
[4]此后浏览器再请求业务接口,sessionId随cookie带上
[5]服务端查sessionId校验session
[6]成功后正常做业务处理,返回结果
2.典型的Token登录/验证流程
[1]用户登录,服务端校验账号密码,获得用户信息
[2]把用户信息、token配置编码成token,通过cookie set到浏览器
[3]此后用户请求业务接口,通过cookie携带token
[4]接口校验token有效性,进行正常业务接口处理
3.token的编码
refresh token就是一个专门生成access token的token:
[1]access token用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松灵活
[2]refresh token用来获取access token,有效期可以长一些,通过独立服务和严格的请求方式增加安全性;由于不常验证,也可以如前面的session一样处理
如果refresh token过期,就只能重新登录了。有了refresh token后请求流程如下所示:
4.单点登录
解析:单点登录即一次登录,全线通用。单点登录要求不同域下的系统一次登录,全线通用,通常由独立的SSO系统记录登录状态、下发ticket,各业务系统配合存储和认证ticket。当主域名不同的场景需要独立的认证服务,通常被称为SSO,即一次从A系统引发登录,到B系统不用登录的完整流程。
[1]用户进入A系统,没有登录凭证[ticket],A系统给他跳到SSO
[2]SSO没登录过,也就没有SSO系统下没有凭证,输入账号密码登录
[3]SSO账号密码验证成功,通过接口返回做两件事:一是种下SSO系统下凭证[记录用户在SSO登录状态];二是下发一个ticket
[4]客户端拿到ticket,保存起来,带着请求系统A接口
[5]系统A校验ticket,成功后正常处理业务请求
[6]此时用户第一次进入系统B,没有登录凭证[ticket],B系统给他跳到SSO
[7]SSO登录过,系统下有凭证,不用再次登录,只需要下发ticket
[8]客户端拿到ticket,保存起来,带着请求系统B接口
对浏览器来说,SSO域下返回的数据要怎么存,才能在访问A的时候带上?浏览器对跨域有严格限制,cookie、localStorage等方式都是有域限制的。这就需要也只能由A提供A域下存储凭证的能力:
[1]在SSO域下,SSO不是通过接口把ticket直接返回,而是通过一个带code的URL重定向到系统A的接口上,这个接口通常在A向SSO注册时约定
[2]浏览器被重定向到A域下,带着code访问了A的callback接口,callback接口通过code换取ticket
[3]这个code不同于ticket,code是一次性的,暴露在URL中,只为了传一下换ticket,换完就失效
[4]callback接口拿到ticket后,在自己的域下set cookie成功
[5]在后续请求中,只需要把cookie中的ticket解析出来,去SSO验证就好
[6]访问B系统也是一样
参考文献:
[1]IdentityServer:https://github.com/IdentityServer
[2]IdentityServer4实现OAuth2.0四种模式之授权码模式:https://www.cnblogs.com/liujiabing/p/11482120.html
[3]IdentityServer4 实现OAuth2.0四种模式之密码模式:https://www.cnblogs.com/liujiabing/p/11460486.html
[4]IdentityServer4实现OAuth2.0四种模式之客户端模式:https://www.cnblogs.com/liujiabing/p/11454080.html
[5]IdentityServer4实现Oauth2.0四种模式之隐藏模式:https://www.cnblogs.com/liujiabing/p/11474131.html
[6]OAuth 2.0的四种方式:http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
[7]IdentityServer4官方文档:https://identityserver4.readthedocs.io/
[8]GitHub OAuth 第三方登录示例教程:https://www.ruanyifeng.com/blog/2019/04/github-oauth.html
[9]JWT:https://jwt.io/
[10]前端鉴权必须了解的5个兄弟:https://mp.weixin.qq.com/s/vh36oOuFmeIkGfw8HsmG3g
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/223079.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...