Abp vNext Token
Abp vNext Token
Abp vNext 版本:5.3
Abp vNext 使用的是IdentityServer4
目录
Abp vNext 基本使用
Abp vNext 增删改查
Abp vNext Token
Abp vNext单点登录
Abp vNext自定义OpenIdDict登录
创建项目
abp new abpdemo --template app --ui none --separate-identity-server
IdentityServer4
提供了八个API
/.well-known/openid-configuration
/connect/authorize
/connect/token
/connect/userinfo
/connect/deviceauthorization
/connect/introspect
/connect/revocation
/connect/endsession
具体使用方式看官方文档的ENDPOINTS
部分,我就记录一些常用的
http://docs.identityserver.io/en/latest/
https://identityserver4.readthedocs.io/en/latest/
获取 token
/api/account/login
只是验证登录,并不返回token
Abp中获取token的接口是/connect/token
参数是来自Body
的x-www-form-urlencoded
类型,不需要access_token
必要参数
{
grant_type : "password",
username : "admin",
password : "1q2w3E*",
client_id : "dbpdemo_App"
}
grant_type
根据数据库中的IdentityServerClientGrantTypes
表的GrantType
字段client_id
根据数据库中的IdentityServerClients
表的ClientId
字段
注意
首先就是IdentityServer
的ip端口,如果创建项目时使用了--separate-identity-server
参数,那么WebAPI和IdentityServer的端口就不一样
HttpApi.Host
的appsettings.json
中的AuthServer.Authority
必须和IdentityServer
的appsettings.json
中的App.SelfUrl
一模一样,否则在验证Issuer
的时候会报异常,状态码401
还有可能会报SSL
证书异常,状态码500
,这个就需要配置SSL
证书了
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.
---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'System.String'.
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch
还有个问题,即使前端的请求数据正确,也可能会出现invalid_client
这样的返回值,需要使用qs.stringify()
序列化数据再请求,我也不懂为什么
还有就是ip的问题,localhost
和127.0.0.1
是不一样的,可能引起401
获取用户信息
有两种方式,都是将token放到Authorization
-
/connect/userInfo
-
ICurrentUser
[ApiController]
[Route("/api/v1/[controller]")]
public class UserController : AbpControllerBase
{
private readonly ICurrentUser _currentUser;
public UserController(ICurrentUser currentUser)
{
this._currentUser = currentUser;
}
[HttpGet("GetCurrentUser")]
[Authorize]
public async Task<ActionResult> GetCurrentUser()
{
return Ok(this._currentUser);
}
}
撤销令牌
IdentityServer4
提供了撤销access_token
和refresh_token
的API,/connect/revocation
这个API接收两个参数token
和token_type_hint
,就是令牌和令牌类型
可以在后端调用这个API去撤销令牌,前端也可以
调用比较麻烦
client_id
:IdentityServerClients
表的ClientId
字段client_secret
:IdentityServerClientSecrets
表的Value
字段,要对应ClientId
两种调用方式
不加验证,这样需要client_id
和client_secret
参数
加验证,把client_id
和client_secret
分别加入Username
和Password
,Body就不需要client_id
和client_secret
了
其实这里并不能使access_token
过期,只能使refresh_token
过期,我试过了,因为jwt生成的token信息是固定的,单纯校验token信息是不够的,所以还是redis好使
双token策略
- 在后端设置一个校验token的
IAuthorizationFilter
过滤器,检查token的有效期,到了差不多的时间就在response
中设置一个标识,由前端校验这个 - 在前端设置一个
response
拦截器,校验响应中是否具有标识,有标识则在请求中带上refresh_token
,然后刷新本地access_token
和refresh_token
refresh_token
只有前端第一次接收和第一次使用时才会在网络中传输,安全性比较高
refresh_token
的使用方式还是/connect/token
,但是参数不太一样,也不需要access_token
{
grant_type : "refresh_token",
refresh_token : "refresh_token",
client_id : "dbpdemo_App"
}
再次使用refresh_token
发送请求,原先的refresh_token
已经失效,access_token
则需要等到有效时间结束,毕竟只是校验token规则
未使用refresh_token
就重新登录去获取access_token
和refresh_token
,那么原先的refresh_token
仍然有效
如果需要access_token
和refresh_token
都失效,即单点登录,可以将access_token
放到redis,在WebApi中写一个中间件或者过滤器,在校验access_token
之前先读取redis,刷新时将旧的access_token
删除,这样做的缺点就是一个用户只能使用一个token,不适合多个客户端使用
刷新token时让旧token过期,如果前端一次发送多个异步请求,那么刷新token后其它请求的处理就比较头疼了,用redis解决还蛮简单的,比如给旧token设置30秒的有效期,写一个中间件/过滤器,在验证token过期时读取redis
XSRF-TOKEN
前端除GET
以外请求可能会报这个异常
The required antiforgery header value "RequestVerificationToken" is not present.
就是防XSRF攻击
用的,Abp vNext默认开启这个,在Swagger或者前端的Cookie里是可以看到有一个XSRF-TOKEN
,除了GET
请求都需要这个token,记得加到请求的header里,对应的属性是RequestVerificationToken
,Postman不需要这个也能请求成功,小坑
也可以选择关闭这个验证,在HttpApi.Host
项目中配置AntiForgery
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAntiForgeryOptions>(options =>
{
//关闭POST的XSRF-TOKEN验证
options.AutoValidateIgnoredHttpMethods.Add("POST");
});
}
根据abp的官方文档,这个验证一般是对Razor用的,WebApi的话,只要header带上RequestVerificationToken
即可,什么值都可以,为空也行,所以就是没用,倒是可以自己写一个
如果需要手动验证可以使用[AbpValidateAntiForgeryToken]
标识控制器的函数
Abp vNext Token 结束
这个说实话,写的有点水,主要是懒了,理解就行,摆了