授权令牌在 ASP.NET Core 中未绑定

我正在调用这样的 REST api:


HttpClient client;

var uri = new Uri(Const.GetUserAccount);

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("accessToken", App.AccessToken);

var response = await client.GetAsync(uri);

这是我的动作签名(accessToken 为空):


public async Task<ActionResult> GetAccountAsync([FromHeader] string accessToken)

令牌位于 Request.Headers.HeaderAuthorization 中,其值为:


"accessToken" + a space + the guid

这似乎很奇怪。不应该有一个名称值对吗?喜欢:


“accessToken”:“GUID”


这就是它不具有约束力的原因吗?如果是这样,我该如何正确传递它?如果没有,我做错了什么?


慕工程0101907
浏览 258回答 1
1回答

忽然笑

这就是它不具有约束力的原因吗?原因是您的操作方法需要accessToken来自请求标头:public async Task<ActionResult> GetAccountAsync([FromHeader] string accessToken)AccessToken: xxx_yyy_zzz虽然您在 request 中没有这样的标头。如果您发送如下请求:GET https://localhost:44323/api/values/account HTTP/1.1accessToken : xxx_yyy_zzzModelBinder 将绑定accessToken.如果是这样,我该如何正确传递它?我不确定您为什么要accessToken在操作方法内获取。但是,如果您确实需要模型绑定的访问令牌,那么至少有两种方法可以做到这一点:一种方法是更改您的操作方法以Authorization直接获取标题:public async Task<ActionResult> GetAccount2Async([FromHeader] string authorization)&nbsp;{&nbsp; &nbsp; if (String.IsNullOrEmpty(authorization)) { /* */ }&nbsp; &nbsp; if (!authorization.StartsWith("accessToken",StringComparison.OrdinalIgnoreCase)) { /* */ }&nbsp; &nbsp; var token = authorization.Substring("accessToken".Length).Trim();&nbsp; &nbsp; // ...}当您发送标头为Authorization : accessToken xxx_yyy_zzz.但是,上面的方法并不干净。更好的方法是创建自定义ModelBinder.首先让我们创建一个虚拟类来保存 accessToken 值:public class AccessTokenAuthorizationHeader{&nbsp; &nbsp; public string TokenValue { get; set; }}这是一个简单的模型绑定器,它将从 headers 中检索访问令牌:public class AuthorizationHeaderBinder : IModelBinder{&nbsp; &nbsp; const string DEFAULT_ACCESS_TOKEN_AUTH_HEADER_PREFIX = "accessToken";&nbsp; &nbsp; public Task BindModelAsync(ModelBindingContext bindingContext)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); }&nbsp; &nbsp; &nbsp; &nbsp; var modelName = bindingContext.BinderModelName;&nbsp; &nbsp; &nbsp; &nbsp; if (string.IsNullOrEmpty(modelName)) { modelName = DEFAULT_ACCESS_TOKEN_AUTH_HEADER_PREFIX; }&nbsp; &nbsp; &nbsp; &nbsp; var authorization = bindingContext.HttpContext.Request.Headers["Authorization"].FirstOrDefault();&nbsp; &nbsp; &nbsp; &nbsp; if (String.IsNullOrWhiteSpace(authorization)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Task.CompletedTask;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (!authorization.StartsWith(modelName, StringComparison.OrdinalIgnoreCase)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Task.CompletedTask;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; var token = authorization.Substring(modelName.Length).Trim();&nbsp; &nbsp; &nbsp; &nbsp; bindingContext.Result = ModelBindingResult.Success(new AccessTokenAuthorizationHeader() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TokenValue =token,&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; return Task.CompletedTask;&nbsp; &nbsp; }}最后,AccessTokenAuthorizationHeader用一个ModelBinderAttribute:[ModelBinder(BinderType =typeof(AuthorizationHeaderBinder))]public class AccessTokenAuthorizationHeader{&nbsp; &nbsp; public string TokenValue { get; set; }}现在我们可以自动绑定它了:[HttpGet("Account3")]public async Task<ActionResult> GetAccount3Async(AccessTokenAuthorizationHeader accessToken) {&nbsp; &nbsp; var result =new JsonResult(accessToken?.TokenValue);&nbsp; &nbsp; return result;}让我们用一个 requset 测试它:GET https://localhost:44323/api/values/account3 HTTP/1.1Authorization : accessToken 111111响应将是:HTTP/1.1 200 OKTransfer-Encoding: chunkedContent-Type: application/json; charset=utf-8Server: KestrelX-SourceFiles: =?UTF-8?B?RDpccmVwb3J0XDIwMThcOVw5LTEzXFNPLkF1dGhvcml6YXRpb25IZWFkZXJcQXBwXEFwcFxhcGlcdmFsdWVzXGFjY291bnQz?=X-Powered-By: ASP.NETDate: Thu, 13 Sep 2018 01:54:25 GMT"111111"
打开App,查看更多内容
随时随地看视频慕课网APP