标签:单位 wordpress oct 视频编辑 回调 生成 跳转 概念 receive
原文:http://www.cnblogs.com/xishuai/p/aspnet-webapi-owin-oauth2.html
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的 2 小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth 让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。
以上概念来自:https://zh.wikipedia.org/wiki/OAuth
OAuth 是什么?为什么要使用 OAuth?上面的概念已经很明确了,这里就不详细说明了。
阅读目录:
开源地址:https://github.com/yuezhongxin/OAuth2.Demo
关于 OAuth 2.0 的运行流程(来自 RFC 6749):
这里我们模拟一个场景:用户听落网,但需要登录才能收藏期刊,然后用快捷登录方式,使用微博的账号和密码登录后,落网就可以访问到微博的账号信息等,并且在落网也已登录,最后用户就可以收藏期刊了。
结合上面的场景,详细说下 OAuth 2.0 的运行流程:
图中的名词解释:
其实,我不是很理解 ABC 操作,我觉得 ABC 可以合成一个 C:落网打开微博的授权页面,用户输入微博的账号和密码,请求验证。
OAuth 2.0 四种授权模式:
下面我们使用 ASP.NET WebApi OWIN,分别实现上面的四种授权模式。
简单解释:落网提供一些授权凭证,从微博授权服务获取到 authorization_code,然后根据 authorization_code,再获取到 access_token,落网需要请求微博授权服务两次。
第一次请求授权服务(获取 authorization_code),需要的参数:
第二次请求授权服务(获取 access_token),需要的参数:
第二次请求授权服务(获取 access_token),返回的参数:
ASP.NET WebApi OWIN 需要安装的程序包:
在项目中创建 Startup.cs 文件,添加如下代码:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
var OAuthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
AuthenticationMode = AuthenticationMode.Active,
TokenEndpointPath = new PathString("/token"), //获取 access_token 授权服务请求地址
AuthorizeEndpointPath=new PathString("/authorize"), //获取 authorization_code 授权服务请求地址
AccessTokenExpireTimeSpan = TimeSpan.FromSeconds(10), //access_token 过期时间
Provider = new OpenAuthorizationServerProvider(), //access_token 相关授权服务
AuthorizationCodeProvider = new OpenAuthorizationCodeProvider(), //authorization_code 授权服务
RefreshTokenProvider = new OpenRefreshTokenProvider() //refresh_token 授权服务
};
app.UseOAuthBearerTokens(OAuthOptions); //表示 token_type 使用 bearer 方式
}
}
OpenAuthorizationServerProvider 示例代码:
public class OpenAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
/// <summary>
/// 验证 client 信息
/// </summary>
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
{
context.TryGetFormCredentials(out clientId, out clientSecret);
}
if (clientId != "xishuai")
{
context.SetError("invalid_client", "client is not valid");
return;
}
context.Validated();
}
/// <summary>
/// 生成 authorization_code(authorization code 授权方式)、生成 access_token (implicit 授权模式)
/// </summary>
public override async Task AuthorizeEndpoint(OAuthAuthorizeEndpointContext context)
{
if (context.AuthorizeRequest.IsImplicitGrantType)
{
//implicit 授权方式
var identity = new ClaimsIdentity("Bearer");
context.OwinContext.Authentication.SignIn(identity);
context.RequestCompleted();
}
else if (context.AuthorizeRequest.IsAuthorizationCodeGrantType)
{
//authorization code 授权方式
var redirectUri = context.Request.Query["redirect_uri"];
var clientId = context.Request.Query["client_id"];
var identity = new ClaimsIdentity(new GenericIdentity(
clientId, OAuthDefaults.AuthenticationType));
var authorizeCodeContext = new AuthenticationTokenCreateContext(
context.OwinContext,
context.Options.AuthorizationCodeFormat,
new AuthenticationTicket(
identity,
new AuthenticationProperties(new Dictionary<string, string>
{
{"client_id", clientId},
{"redirect_uri", redirectUri}
})
{
IssuedUtc = DateTimeOffset.UtcNow,
ExpiresUtc = DateTimeOffset.UtcNow.Add(context.Options.AuthorizationCodeExpireTimeSpan)
}));
await context.Options.AuthorizationCodeProvider.CreateAsync(authorizeCodeContext);
context.Response.Redirect(redirectUri + "?code=" + Uri.EscapeDataString(authorizeCodeContext.Token));
context.RequestCompleted();
}
}
/// <summary>
/// 验证 authorization_code 的请求
/// </summary>
public override async Task ValidateAuthorizeRequest(OAuthValidateAuthorizeRequestContext context)
{
if (context.AuthorizeRequest.ClientId == "xishuai" &&
(context.AuthorizeRequest.IsAuthorizationCodeGrantType || context.AuthorizeRequest.IsImplicitGrantType))
{
context.Validated();
}
else
{
context.Rejected();
}
}
/// <summary>
/// 验证 redirect_uri
/// </summary>
public