- 后端
- API设计
【免费下载链接】RestSharp
Simple REST and HTTP API Client for .NET
RestSharp 内置了一套分层清晰的认证体系,覆盖 HTTP Basic、OAuth1(含 xAuth 与 0-legged 流程)、OAuth2 令牌携带以及 JWT Bearer Token 等常见场景,同时通过IAuthenticator接口与AuthenticatorBase抽象基类支持完全自定义的认证逻辑。本文将基于 RestSharp v112 版本文档(authenticators.md),结合仓库源码与测试用例,逐一拆解各类认证器的构造方式、配置位置、底层实现与调用时机,帮助你为不同类型的 API 客户端选择并落地正确的认证方案。
认证器的两种挂载方式
RestSharp 允许你把认证器挂载在两个层级上,二者取其一即可:
- 客户端级(client-wide):通过
RestClientOptions.Authenticator属性设置,作用于该客户端发起的每一次请求,适合整个 API 服务使用同一种认证方式的场景:
var options = new RestClientOptions("https://example.com") { Authenticator = new HttpBasicAuthenticator("username", "password") }; var client = new RestClient(options);- 请求级(per-request):通过
RestRequest.Authenticator属性设置,只对当前这一次请求生效,适合同一客户端内不同接口使用不同认证方式的场景:
var request = new RestRequest("/api/users/me") { Authenticator = new HttpBasicAuthenticator("username", "password") }; var response = await client.ExecuteAsync(request, cancellationToken);从源码实现看,无论哪种挂载方式,最终认证逻辑都收敛到同一个接口。IAuthenticator 的定义极为精简,只有一个异步方法:
public interface IAuthenticator { ValueTask Authenticate(IRestClient client, RestRequest request, CancellationToken cancellationToken = default); }也就是说,任何认证器本质上都是"在请求发出前,往RestRequest上附加认证参数"的一段逻辑。RestSharp 内置认证器大多继承自 AuthenticatorBase,该基类保存了一个可变的Token字符串,并通过一个抽象方法把令牌转换为请求参数:
public abstract class AuthenticatorBase(string token) : IAuthenticator { protected string Token { get; set; } = token; protected abstract ValueTask<Parameter> GetAuthenticationParameter(string accessToken); public async ValueTask Authenticate(IRestClient client, RestRequest request, CancellationToken cancellationToken = default) => request.AddOrUpdateParameter(await GetAuthenticationParameter(Token).ConfigureAwait(false)); }因此,RestSharp 所有内置认证器的职责都很单一:把认证信息翻译成一个Parameter(通常是HeaderParameter,也可能是GetOrPostParameter),再通过AddOrUpdateParameter附加到请求上。这一设计也让自定义认证器变得非常直接。
Basic 认证
HttpBasicAuthenticator用于 HTTP Basic 访问认证。它把username:password按 Base64 编码后放入Authorization请求头,编码结果以Basic前缀开头。
最常用的两参数构造方式:
var options = new RestClientOptions("https://example.com") { Authenticator = new HttpBasicAuthenticator("username", "password") }; var client = new RestClient(options);从 HttpBasicAuthenticator 源码可以看到,它还提供一个三参数重载,允许指定字符编码:
public class HttpBasicAuthenticator(string username, string password, Encoding encoding) : AuthenticatorBase(GetHeader(username, password, encoding)) { public HttpBasicAuthenticator(string username, string password) : this(username, password, Encoding.UTF8) { } static string GetHeader(string username, string password, Encoding encoding) => Convert.ToBase64String(encoding.GetBytes($"{username}:{password}")); protected override ValueTask<Parameter> GetAuthenticationParameter(string accessToken) => new(new HeaderParameter(KnownHeaders.Authorization, $"Basic {accessToken}")); }要点说明:
- 默认使用UTF-8编码拼接
username:password后做 Base64;部分旧服务器可能期望 ISO-8859-1 编码,此时可以传入自定义Encoding。 - 编码在构造器里一次性完成,之后每次请求都复用同一个 Base64 字符串。
- 认证参数以 HeaderParameter 形式写入
Authorization头。仓库测试 HttpBasicAuthTests.cs 对该行为有专门覆盖。
OAuth1
OAuth1 是签名型认证协议,RestSharp 的OAuth1Authenticator会为请求自动生成并附加所需的 OAuth 参数与签名。它默认使用HMAC-SHA1生成签名,但每个静态工厂方法都支持通过signatureMethod参数切换算法。
底层签名与参数生成由 OAuthWorkflow 完成:它负责生成oauth_timestamp、oauth_nonce、oauth_signature_method、oauth_version等参数,并按 RFC 5849 的规则拼接签名基串后计算签名。支持的签名算法定义在 Enums.cs 中:
public enum OAuthSignatureMethod { HmacSha1, HmacSha256, PlainText, RsaSha1 }对应的测试见 OAuth1SignatureTests.cs 与 OAuth1AuthTests.cs。
OAuth1Authenticator的公开属性(见 OAuth1Authenticator.cs)非常完备,包括ConsumerKey、ConsumerSecret、Token、TokenSecret、Verifier、Version、CallbackUrl、SessionHandle、ClientUsername、ClientPassword、Realm、SignatureMethod、ParameterHandling等。日常使用只需调用静态工厂方法,无需手动逐项赋值。
获取 Request Token(三步授权流程第一步)
获取临时 request token 是 OAuth1 三足授权流程的常规第一步,使用ForRequestToken工厂方法,只需consumerKey和consumerSecret:
var options = new RestClientOptions("https://api.twitter.com") { Authenticator = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret) }; var client = new RestClient(options); var request = new RestRequest("oauth/request_token");响应中应包含 token 与 token secret,用于后续完成授权。如果需要指定回调地址,可给认证器赋CallbackUrl属性:
var authenticator = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret); authenticator.CallbackUrl = "https://myapp.example.com/callback";实际上ForRequestToken还提供了一个直接接收回调地址的重载(见 OAuth1Authenticator.cs)。
换取 Access Token(三步授权流程第三步)
拿到 request token 后,用ForAccessToken换取 access token,需要传入consumerKey、consumerSecret、oauthToken与oauthTokenSecret:
var authenticator = OAuth1Authenticator.ForAccessToken( consumerKey, consumerSecret, oauthToken, oauthTokenSecret ); var options = new RestClientOptions("https://api.twitter.com") { Authenticator = authenticator }; var client = new RestClient(options); var request = new RestRequest("oauth/access_token");如果三步流程的第二步返回了 verifier(用户授权后服务端下发的校验码),使用带verifier参数的重载:
var authenticator = OAuth1Authenticator.ForAccessToken( consumerKey, consumerSecret, oauthToken, oauthTokenSecret, verifier );ForAccessToken的可选signatureMethod参数同样默认是HmacSha1。响应中应包含可用于访问受保护资源的 access token。
刷新 Access Token
RestSharp 提供两个接受sessionHandle的刷新重载(ForAccessTokenRefresh,见 OAuth1Authenticator.cs),分别对应"无 verifier"与"有 verifier"两种情况:
// 不带 verifier 的刷新 var authenticator = OAuth1Authenticator.ForAccessTokenRefresh( consumerKey, consumerSecret, oauthToken, oauthTokenSecret, sessionHandle ); // 带 verifier 的刷新 var authenticator = OAuth1Authenticator.ForAccessTokenRefresh( consumerKey, consumerSecret, oauthToken, oauthTokenSecret, verifier, sessionHandle );访问受保护资源
拿到 access token 后,调用ForProtectedResource获取用于访问受保护资源的认证器:
var authenticator = OAuth1Authenticator.ForAccessToken( consumerKey, consumerSecret, accessToken, accessTokenSecret ); var options = new RestClientOptions("https://api.twitter.com/1.1") { Authenticator = authenticator }; var client = new RestClient(options); var request = new RestRequest("statuses/update.json", Method.Post) .AddParameter("status", "Hello Ladies + Gentlemen, a signed OAuth request!") .AddParameter("include_entities", "true");需要注意,源码中AddOAuthData会明确拒绝在 base URL 中携带查询字符串的用法(抛ApplicationException提示改用AddDefaultQueryParameter),这是使用 OAuth1 时容易踩到的坑。
xAuth
xAuth 是 OAuth1 的简化变体:直接把用户名密码以x_auth_username和x_auth_password请求参数发送,从而直接换取 access token。该方式并未被广泛支持,但 RestSharp 仍然保留了它。通过ForClientAuthentication创建:
var authenticator = OAuth1Authenticator.ForClientAuthentication( consumerKey, consumerSecret, username, password );从 OAuthWorkflow.cs 可以看到,xAuth 流程会额外生成x_auth_mode=client_auth参数,且签名基于用户名密码与 consumer 密钥计算。
0-legged OAuth
0-legged(零足)OAuth 场景下,access token 认证器可把consumerSecret传为null,用于对访问令牌已预先签发、无需完整授权流程的情况:
var authenticator = OAuth1Authenticator.ForAccessToken( consumerKey, null, oauthToken, oauthTokenSecret );OAuth1 的参数携带方式
OAuth1Authenticator还暴露了ParameterHandling属性,支持两种 OAuth 参数携带策略(见 Enums.cs):
HttpAuthorizationHeader(默认):把所有oauth_*参数拼进Authorization请求头;UrlOrPostParameters:把参数作为 URL 查询串或 POST 表单参数发送。
默认工厂方法统一采用HttpAuthorizationHeader模式,并配合Escaped的签名处理方式。
OAuth2
RestSharp 内置了两个非常简单的 OAuth2 认证器——它们只负责把已经获取到的 access token 附加到请求上,本身不参与令牌的获取与刷新。
以查询参数携带令牌:OAuth2UriQueryParameterAuthenticator
该认证器只接受 access token 一个构造参数,会把令牌作为名为oauth_token的查询参数附加到请求 URL 上(见 OAuth2UriQueryParameterAuthenticator.cs):
var authenticator = new OAuth2UriQueryParameterAuthenticator(accessToken);其内部实现正是把令牌包装成GetOrPostParameter("oauth_token", accessToken)——这也是它与其它认证器(产出HeaderParameter)的关键区别。
以请求头携带令牌:OAuth2AuthorizationRequestHeaderAuthenticator
该认证器提供两个构造重载:
- 单参数:只传 access token,此时默认令牌类型为
OAuth; - 双参数:可额外指定令牌类型(如
Bearer)。
它会按"{tokenType} {accessToken}"的格式写入Authorization头(见 OAuth2AuthorizationRequestHeaderAuthenticator.cs):
var authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator( token, "Bearer" ); var options = new RestClientOptions("https://example.com") { Authenticator = authenticator }; var client = new RestClient(options);上述代码等同于后续 JWT 小节中JwtAuthenticator的效果——每个请求都会携带Authorization: Bearer <token>。
由于这两个认证器都不负责获取令牌本身,如果你需要"自取令牌"的完整 OAuth2 客户端,可以参考仓库中的 示例 OAuth2 认证器(位于 usage 示例文档),它展示了如何请求 token endpoint 并把拿到的 bearer token 自动附加到后续请求。
补充:仓库中还有一个能力更强的 OAuth2TokenAuthenticator。它接受一个异步的
Func<CancellationToken, Task<OAuth2Token>>令牌获取委托,会在内部缓存令牌并在过期后自动重新获取;通过SemaphoreSlim保证并发安全。它适用于非标准 OAuth2 流程或自定义令牌提供方,相关设计文档见 docs/plans。
JWT
JwtAuthenticator是携带 JWT Bearer Token 的最简实现:
var authenticator = new JwtAuthenticator(myToken); var options = new RestClientOptions("https://example.com") { Authenticator = authenticator }; var client = new RestClient(options);每次请求时,它都会添加值为Bearer <your token>的Authorization头。
从 JwtAuthenticator.cs 源码可以看到两个值得注意的实现细节:
- 自动补前缀:如果传入的 token 本身不以
"Bearer "开头,构造器会自动补上该前缀;如果已经带前缀则原样保留。同时会通过Ensure.NotEmptyString拒绝空字符串。 - 运行期换令牌:
SetBearerToken方法允许在请求执行过程中动态更新令牌,底层只是替换AuthenticatorBase.Token属性:
authenticator.SetBearerToken(newToken);自定义 Authenticator
当内置认证器无法满足需求时,可以直接实现IAuthenticator接口并注册到RestClientOptions:
var authenticator = new SuperAuthenticator(); // implements IAuthenticator var options = new RestClientOptions("https://example.com") { Authenticator = authenticator }; var client = new RestClient(options);Authenticate方法在调用RestClient.Execute或RestClient.Execute<T>时是最先被调用的逻辑之一。它接收当前正在执行的RestRequest,因此你可以访问请求数据的每一个部分(headers、parameters、body 等),对请求做任意形式的改写。
两种推荐的实现路径:
- 直接实现
IAuthenticator:适合完全不依赖令牌缓存的场景,接口只有一个ValueTask Authenticate(...)方法,签名见 IAuthenticator.cs。 - 继承
AuthenticatorBase:适合需要"懒加载令牌并缓存复用"的场景,只需实现抽象方法GetAuthenticationParameter。
仓库的 usage 示例文档 给出了一个真实可运行的参考:TwitterAuthenticator继承AuthenticatorBase,首次调用时发现Token为空,于是内部用HttpBasicAuthenticator请求oauth2/token端点换取 bearer token,随后复用该 token 直到需要刷新。其核心代码模式为:
public class TwitterAuthenticator : AuthenticatorBase { protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken) { Token = string.IsNullOrEmpty(Token) ? await GetToken() : Token; return new HeaderParameter(KnownHeaders.Authorization, Token); } }注意该示例文档同时提示:示例代码为生产级代码,当令牌尚未获取时若多个请求并发执行,可能产生重复获取令牌的副作用,实际生产环境可通过信号量(semaphore)等方式规避。
小结
RestSharp 的认证体系可以用一张表概括:
| 场景 | 推荐认证器 | 附加位置 |
|---|---|---|
| HTTP Basic 用户名密码 | HttpBasicAuthenticator | Authorization: Basic ...头 |
| OAuth1 三步授权/受保护资源 | OAuth1Authenticator.ForRequestToken/ForAccessToken/ForProtectedResource | Authorization头(默认) |
| OAuth1 简化/xAuth | OAuth1Authenticator.ForClientAuthentication | Authorization头 +x_auth_*参数 |
| OAuth2 令牌走查询参数 | OAuth2UriQueryParameterAuthenticator | oauth_token查询参数 |
| OAuth2 令牌走请求头 | OAuth2AuthorizationRequestHeaderAuthenticator | Authorization: {tokenType} {token}头 |
| JWT Bearer | JwtAuthenticator(可用SetBearerToken刷新) | Authorization: Bearer <token>头 |
| 完全自定义 | 实现IAuthenticator或继承AuthenticatorBase | 任意位置 |
选择建议:单客户端统一认证时挂载到RestClientOptions;混合认证时挂载到单个RestRequest;需要令牌自动获取与缓存的复杂 OAuth2 场景,优先考虑继承AuthenticatorBase的懒加载模式。仓库中对应的测试(Auth 测试目录)与 OAuth2 认证器测试 是验证各类认证器行为最直接的参考。
- 后端
- API设计
【免费下载链接】RestSharp
Simple REST and HTTP API Client for .NET
相关推荐
RestSharp 认证机制完全指南:Basic、OAuth1、OAuth2、JWT 与自定义 Authenticator
RestSharp 认证机制完全指南:Basic、OAuth1、OAuth2、JWT 与自定义 Authenticator RestSharp 是面向 .NET
后端API设计RestSharp 认证机制全解:Basic、OAuth1、OAuth2 与 JWT 认证器实战指南
RestSharp 认证机制全解:Basic、OAuth1、OAuth2 与 JWT 认证器实战指南 本文以 RestSharp v113 文档中的认证器指南为
后端API设计RestSharp 认证体系完全指南:从 Basic、OAuth1 到 OAuth2 与 JWT 的认证器详解
RestSharp 认证体系完全指南:从 Basic、OAuth1 到 OAuth2 与 JWT 的认证器详解 本指南以 RestSharp v114 版本化文
后端API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考