之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了。官方推荐的.NET 包有

Katana已经不更新了,新的版本是已经是asp.net core 1.0的一部分,实现OAUTH2好的选择可以考虑使用新版或IdentityServer3对应asp.net core 1.0版本为IdentityServer4。

Startup

public partial class Startup
{
private readonly ConcurrentDictionary<string, string> _authenticationCodes = new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = Paths.AuthenticationType,
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString(Paths.LoginPath),
LogoutPath = new PathString(Paths.LogoutPath),
}); app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
TokenEndpointPath = new PathString(Paths.TokenPath),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
OnGrantClientCredentials = GrantClientCredetails
},
//Provider = new ApplicationOAuthProvider(),
AuthorizationCodeProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAuthenticationCode,
OnReceive = ReceiveAuthenticationCode,
},
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
},
ApplicationCanDisplayErrors = true,
#if DEBUG
//HTTPS is allowed only AllowInsecureHttp = false
AllowInsecureHttp = true,
#endif
});
} private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
{
context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
_authenticationCodes[context.Token] = context.SerializeTicket();
} private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
{
string value;
if (_authenticationCodes.TryRemove(context.Token, out value))
{
context.DeserializeTicket(value);
}
} private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(identity);
return Task.FromResult(0);
} private Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(identity);
return Task.FromResult(0);
} private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) || context.TryGetFormCredentials(out clientId, out clientSecret))
{
context.Validated();
}
return Task.FromResult(0);
} private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == Clients.Client1.Id)
{
context.Validated();
//context.Validated(Clients.Client1.RedirectUrl);
}
else if (context.ClientId == Clients.Client2.Id)
{
context.Validated(Clients.Client2.RedirectUrl);
}
return Task.FromResult(0);
} private void CreateRefreshToken(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
} private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}

OAuthController

/// <summary>
/// 授权码模式授权
/// </summary>
/// <returns></returns>
public ActionResult Authorize()
{
var authentication = HttpContext.GetOwinContext().Authentication;
var ticket = authentication.AuthenticateAsync(Paths.AuthenticationType).Result;
var identity = ticket != null ? ticket.Identity : null;
if (identity == null)
{
authentication.Challenge(Paths.AuthenticationType);
return new HttpUnauthorizedResult();
}
var scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');
if (Request.HttpMethod == "POST")
{
if (!string.IsNullOrEmpty(Request.Form.Get("submit.Grant")))
{
identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);
foreach (var scope in scopes)
{
identity.AddClaim(new Claim("urn:oauth:scope", scope));
}
authentication.SignIn(identity);
}
if (!string.IsNullOrEmpty(Request.Form.Get("submit.Login")))
{
authentication.SignOut("Application");
authentication.Challenge("Application");
return new HttpUnauthorizedResult();
}
}
return View();
}

AccountController

/// <summary>
/// 用户登录
/// </summary>
/// <returns></returns>
public ActionResult Login()
{
var authentication = HttpContext.GetOwinContext().Authentication;
if (Request.HttpMethod == "POST")
{
var isPersistent = !string.IsNullOrEmpty(Request.Form.Get("isPersistent"));
if (!string.IsNullOrEmpty(Request.Form.Get("submit.Signin")))
{
authentication.SignIn(
new AuthenticationProperties { IsPersistent = isPersistent },
new ClaimsIdentity(new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, Request.Form["username"]) }, "Application"));
}
}
return View();
} /// <summary>
/// 退出
/// </summary>
/// <returns></returns>
public ActionResult Logout()
{
return View();
}

调试

获得授权码

GET /oauth/authorize?client_id=irving&redirect_uri=http://localhost:38500/oauth_callback&state=LYUVwcuaGuKeRTjxhdFzhQ&scope=bio

%20notes&response_type=code HTTP/1.1

http://localhost:56889/oauth/authorize?

client_id=irving&redirect_uri=http://localhost:38500/oauth_callback&state=LYUVwcuaGuKeRTjxhdFzhQ&scope=bio%20notes&response_type=code

页面重定向

HTTP/1.1 302 Found

Location: /oauth_callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

http://localhost:56889/oauth_callback?code=0aa3e35bd515413bb93bdb6fb015591cc763a8d30c554730a07ebd39e3149252&state=LYUVwcuaGuKeRTjxhdFzhQ

获得令牌

POST /token HTTP/1.1

Host: server.example.com

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=929dc42905a24e79bdf028f7043769acddd90056ca8141708b3834ec174e8083&state=LYUVwcuaGuKeRTjxhdFzhQ&redirect_uri=http://localhost:38500/oauth_callback

源码:https://github.com/zhouyongtao/SecuringForWebAPI/tree/master/KatanaForWebAPI

注意事项

资源服务器识别认证服务器颁发的令牌, 需要配置相同的machinekey

<machineKey decryptionKey="B7EFF1C5839A624E3F97D0268917EDE82F408D2ECBFAC817" validation="SHA1" validationKey="C2B8DF31AB9624D69428066DFDA1A479542825F3B48865C4E47AF6A026F22D853DEC2B3248DF268599BF89EF78B9E86CA05AC73577E0D5A14C45E0267588850B" />

REFER:

http://beginor.github.io/2015/01/24/oauth2-server-with-owin.html

http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】的更多相关文章

  1. 【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务

    前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似. 让用户通过客户端去获取自己的tok ...

  2. IdentityServer4 (3) 授权码模式(Authorization Code)

    写在前面 1.源码(.Net Core 2.2) git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git 2.相关章节 2.1. ...

  3. Apache Oltu 实现 OAuth2.0 服务端【授权码模式(Authorization Code)】

    要实现OAuth服务端,就得先理解客户端的调用流程,服务提供商实现可能也有些区别,实现OAuth服务端的方式很多,具体可能看 http://oauth.net/code/ 各语言的实现有(我使用了Ap ...

  4. Owin中间件搭建OAuth2.0认证授权服务体会

    继两篇转载的Owin搭建OAuth 2.0的文章,使用Owin中间件搭建OAuth2.0认证授权服务器和理解OAuth 2.0之后,我想把最近整理的资料做一下总结. 前两篇主要是介绍概念和一个基本的D ...

  5. 使用Owin中间件搭建OAuth2.0认证授权服务器

    前言 这里主要总结下本人最近半个月关于搭建OAuth2.0服务器工作的经验.至于为何需要OAuth2.0.为何是Owin.什么是Owin等问题,不再赘述.我假定读者是使用Asp.Net,并需要搭建OA ...

  6. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】

    密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权 ...

  7. 【PHP】基于ThinkPHP框架搭建OAuth2.0服务

    [PHP]基于ThinkPHP框架搭建OAuth2.0服务 http://leyteris.iteye.com/blog/1483403

  8. OAuth2.0学习(1-6)授权方式3-密码模式(Resource Owner Password Credentials Grant)

    授权方式3-密码模式(Resource Owner Password Credentials Grant) 密码模式(Resource Owner Password Credentials Grant ...

  9. OAuth 第三方登录授权码(authorization code)方式的小例子

    假如上面的网站A,可以通过GitHub账号登录: 下面以OAuth其中一种方式,授权码(authorization code)方式为例. 一.第三方登录的原理 所谓第三方登录,实质就是 OAuth 授 ...

随机推荐

  1. 内省(Introspector)

    内省(Introspector) 是Java 语言对 JavaBean 类属性.事件的一种缺省处理方法 目的:主要用于传递数据信息,这种类中的方法主要用于访问私有的字段(且方法名符合某种命名规则) p ...

  2. uniDBGrid导入数据库(转红鱼儿)

    有朋友问如何将excel导入数据库,这是我做的uniGUI项目中代码,实现uniDBGrid导入数据库的函数,因为用了kbmMW,所以你看到是将uniDBGrid导入kbmMWClientQuery, ...

  3. 通过Percona XtraBackup添加一个slave

    假设我的master是172.16.15.8,要添加的slave是172.16.15.9 1:在主服务器执行备份操作(172.16.15.8) /usr/bin/innobackupex --comp ...

  4. php乱码解决

    代码示例: <?phpheader("Content-type: text/hml; charset=utf-8");echo "holl 欢迎光临小站,现在正在建 ...

  5. 样式link属性media用法--媒体类型查询

    引用外部样式使用link 你可能想针对将要显示页面的设备类型(桌面PC.笔记本电脑.平板电脑.手机或者甚至页面的印刷版本)来调整页面的样式,可以利用一个media属性, 在<link>元素 ...

  6. 5.Mybatis的输出映射(就是对查询的结果集的映射)

    Mybatis的输出映射,也就是对查询结果集的一个映射,主要有两种: 1.resultType(不需要配置,可以直接用) 一般是实体类 基本类型也可以 2.resultMap(需要配置resultMa ...

  7. .net 更新数据 ado.net parameter

    UPDATE yborder_ordernotes SET recoder400= @FileAddress, havefile400 = 1 WHERE id = @OrderID Maticsof ...

  8. sublimetext

    下载地址:http://www.sublimetext.com/ 详情:http://baike.baidu.com/link?url=uoObJWXyy_-zu52HuOKzfKuwHEpL2JQn ...

  9. PHP--字符串处理函数

    字符串的声明 1. 2. 3. [注]单引号与双引号声明字符串的区别: 1.strlen():获取字符串长度 2.substr():截取字符串 3.strpos():查找字符串在指定字符串中的位置 4 ...

  10. [linux] 更改目录显示颜色

    第一.创建配置文件 $dircolors -p>~/.dircolors 第二.编辑配置文件 打开文件: $vi ~/.dircolors 找到这一行: DIR ; # directory #可 ...