OAuth 2.0是一个应用之间彼此访问数据的开源授权协议。比如,一个游戏应用可以访问Facebook的用户数据或者一个基于地理的应用可以访问Foursquare的用户数据等。下面是一张阐述该概念的图:
用户访问web游戏应用,该游戏应用要求用户通过Facebook登录。用户登录到了Facebook,再重定向会游戏应用, 游戏应用就可以访问用户在Facebook的数据了,并且该应用可以代表用户向Facebook调用函数(如发送状态更新)。
下图说明了OAuth2.0整个授权过程:
OAuth 2.0为用户和应用定义了如下角色,这些角色在下图中表示为:
更详细的介绍可参考:https://www.w3cschool.cn/oauth2/5yej1ja2.html。
客户端使用自己的名义,而不是用户的名义,向“服务提供商” 进行认证。如下图展示了整个流程:
可以得出一个大概的结论
https://xx.com:8081/grant_type=client_credentials&client_id=ClientCredentials&client_secret=secret
上面 URL 中,grant_type
参数等于client_credentials
表示采用凭证式,client_id
和client_secret
用来让认证服务确认Client的身份。
Authorization
字段,令牌就放在这个字段里面。
curl -H "Authorization: Bearer ACCESS_TOKEN" \
"https://xx:8008/api/Values"
上面命令中,ACCESS_TOKEN
就是拿到的令牌。
从nuget中引入下面组件:注意以下六个组件都要安装。
新增Startup.cs
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(ResourceService.Startup))]
namespace ResourceService
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
新增Startup.Auth.cs
using Owin;
namespace ResourceService
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// 这句是资源服务器认证token的关键,认证逻辑在里边封装好了,我们看不到
app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions());
}
}
}
新增ValuesController.cs
using System.Web.Http;
namespace ResourceService.Controllers
{
[Authorize]
public class ValuesController : ApiController
{
public string Get()
{
return "qiuxainhu";
}
}
}
web.config配置文件中添加machineKey
引入以下组件:注意以下五个组件都要引用
新增Startup.cs
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(ClientCredentialService.Startup))]
namespace ClientCredentialService
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
新增Startup.Auth.cs
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
namespace ClientCredentialService
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
//创建OAuth授权服务器
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),//access_token 授权服务请求地址,即http://localhost:端口号/token;
ApplicatiOnCanDisplayErrors= true,
AccessTokenExpireTimeSpan = TimeSpan.FromDays(10),//access_token 过期时间
#if DEBUG
AllowInsecureHttp = true,
#endif
// Authorization server provider which controls the lifecycle of Authorization Server
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientAuthentication = ValidateClientAuthentication,
OnGrantClientCredentials = GrantClientCredetails
}
});
}
///
/// ValidateClientAuthentication方法用来对third party application 认证,
/// 获取客户端的 client_id 与 client_secret 进行验证
/// context.Validated(); 表示允许此third party application请求。
///
///
///
private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId = null;
string clientSecret = null;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
context.TryGetFormCredentials(out clientId, out clientSecret))
{
if (clientId == "123456" && clientSecret == "abcdef")
{
context.Validated();
}
}
return Task.FromResult(0);
}
///
/// 该方法是对客户端模式进行授权的时候使用的
/// 对客户端进行授权,授了权就能发 access token 。
/// 只有这两个方法(ValidateClientAuthentication和GrantClientCredetails)同时认证通过才会颁发token。
private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
{
GenericIdentity genericIdentity = new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType);
ClaimsIdentity claimsIdentity = new ClaimsIdentity(genericIdentity, context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(claimsIdentity);
return Task.FromResult(0);
}
}
}
web.config配置文件中添加machineKey
自此,认证服务项目算是建好了,因为对于客户端模式,认证服务器只需要返回token
新增一个控制台项目,用于测试,如下:
新建一个帮助类ConfigSetting,用于读取配置文件:
using System;
using System.Configuration;
namespace ConfigHelper
{
public class ConfigSetting
{
public static readonly string TOKENPATH = GetAppSettingValue("TOKENPATH");
public static readonly string OAUTH_SERVER_URL=GetAppSettingValue("OAUTH_SERVER_URL");
public static readonly string OAUTH_TOKEN_PATH = GetAppSettingValue("OAUTH_TOKEN_PATH");
public static readonly string CLIENTID = GetAppSettingValue("CLIENTID");
public static readonly string SECRET = GetAppSettingValue("SECRET");
public static readonly string RESOURCE_SERVER_URL = GetAppSettingValue("RESOURCE_SERVER_URL");
public static readonly string RESOURCE_ME_PATH = GetAppSettingValue("RESOURCE_ME_PATH");
private static string GetAppSettingValue(string key)
{
string value = null;
foreach (string item in ConfigurationManager.AppSettings)
{
if (item.Equals(key, StringComparison.CurrentCultureIgnoreCase))
{
value = ConfigurationManager.AppSettings[item];
break;
}
}
return value;
}
}
}
编辑app.config配置文件:
修改program.cs,这里使用方式一HttpClient 来做请求: using Newtonsoft.Json.Linq; 看下运行效果: 修改program.cs,使用方式二DotNetOpenAuth.OAuth2来请求 using DotNetOpenAuth.OAuth2; 使用DotNetOpenAuth.OAuth2需要加下配置文件: "1.0" encoding="utf-8" ?> 看下运行效果: 用户向客户端提供用户名和密码,客户端使用这些信息向认证服务进行认证,密码模式的流程图: 如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。 上面 URL 中, 引入下面组件: 新建Startup.cs文件 using Microsoft.Owin; 新建Startup.Auth.cs文件 using Microsoft.Owin; web.config配置文件中添加machineKey 我们沿用客户端凭证模式中的资源服务。 我们沿用客户端凭证模式中的客户端,这里简单修改下代码: using Newtonsoft.Json.Linq; 效果如下: 通过客户端的后台服务器,与“服务提供商”的认证服务器进行认证。 引入以下组件: 新建Startup.cs using Microsoft.Owin; 新增Startup.Auth.cs using Microsoft.AspNet.Identity; 添加OAuthController.cs代码如下: using DotNetOpenAuth.Messaging; 添加Authorize.cshtml,代码如下: 登录用户:@ViewBag.IdentityName 第三方应用需要你给他开放以下权限 添加AccountController.cs,代码如下: using Microsoft.AspNet.Identity; 添加Login.cshtml,代码如下: @{ 添加Logout.cshtml,代码如下: @{ web.config配置文件中添加machineKey 我们沿用上边的资源服务器 新建一个mvc项目: 添加HomeController,代码如下: using DotNetOpenAuth.Messaging; Index.cshtml代码如下: 运行ClientMvc进行测试,发生如下错误: 解决方法:配置文件中加入如下节点: 运行效果如下: 原文链接:https://www.cnblogs.com/qtiger/p/14871887.html
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
namespace ClientConsole
{
class Program
{
private static string OAUTH_SERVER_URL = ConfigSetting.OAUTH_SERVER_URL;
private static string OAUTH_TOKEN_PATH = ConfigSetting.OAUTH_TOKEN_PATH;
private static string RESOURCE_SERVER_URL = ConfigSetting.RESOURCE_SERVER_URL;
private static string RESOURCE_ME_PATH = ConfigSetting.RESOURCE_ME_PATH;
private static readonly string ClientID = ConfigSetting.CLIENTID;
private static readonly string Secret = ConfigSetting.SECRET;
private static string _AccessToken;
static void Main(string[] args)
{
HttpClient _httpClient = new HttpClient();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("grant_type", "client_credentials");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes(ClientID + ":" + Secret))
);
var respOnse= _httpClient.PostAsync(new Uri(new Uri(OAUTH_SERVER_URL), OAUTH_TOKEN_PATH), new FormUrlEncodedContent(parameters)).Result;
var respOnseValue= response.Content.ReadAsStringAsync().Result;
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
_AccessToken = JObject.Parse(responseValue)["access_token"].Value<string>();
}
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
Console.WriteLine(_httpClient.GetAsync(new Uri(new Uri(RESOURCE_SERVER_URL), RESOURCE_ME_PATH)).Result.Content.ReadAsStringAsync().Result);
Console.ReadKey();
Console.ReadKey();
}
}
}
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace ClientConsole
{
class Program
{
private static string OAUTH_SERVER_URL = ConfigSetting.OAUTH_SERVER_URL;
private static string OAUTH_TOKEN_PATH = ConfigSetting.OAUTH_TOKEN_PATH;
private static string RESOURCE_SERVER_URL = ConfigSetting.RESOURCE_SERVER_URL;
private static string RESOURCE_ME_PATH = ConfigSetting.RESOURCE_ME_PATH;
private static readonly string ClientID = ConfigSetting.CLIENTID;
private static readonly string Secret = ConfigSetting.SECRET;
private static WebServerClient _WebServerClient;
private static string _AccessToken;
static void Main(string[] args)
{
InitializeWebServerClient();
Console.WriteLine("Requesting Token...");
RequestToken();
Console.WriteLine("Access Token: {0}", _AccessToken);
Console.WriteLine("Access Protected Resource");
AccessProtectedResource();
Console.ReadKey();
}
private static void InitializeWebServerClient()
{
Uri authorizationServerUri = new Uri(OAUTH_SERVER_URL);
AuthorizationServerDescription authorizationServer = new AuthorizationServerDescription
{
TokenEndpoint = new Uri(authorizationServerUri, OAUTH_TOKEN_PATH)
};
_WebServerClient = new WebServerClient(authorizationServer, ClientID, Secret);
}
private static void RequestToken()
{
IAuthorizationState state = _WebServerClient.GetClientAccessToken();
Console.WriteLine(state);
_AccessToken = state.AccessToken;
}
private static void AccessProtectedResource()
{
Uri resourceServerUri = new Uri(RESOURCE_SERVER_URL);
HttpClient client = new HttpClient(_WebServerClient.CreateAuthorizingHandler(_AccessToken));
string body = client.GetStringAsync(new Uri(resourceServerUri, RESOURCE_ME_PATH)).Result;
Console.WriteLine(body);
}
}
}三、OWIN实现OAuth 2.0 之密码模式
1、原理
2、过程
https://xx.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID
grant_type
参数是授权方式,这里的password
表示"密码式",username
和password
是 B 的用户名和密码。3、示例
(1)认证服务
using Owin;
[assembly: OwinStartup(typeof(PasswordService.Startup))]
namespace PasswordService
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
namespace PasswordService
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
//创建OAuth授权服务器
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),//获取 access_token 授权服务请求地址,即http://localhost:端口号/token;
ApplicatiOnCanDisplayErrors= true,
AccessTokenExpireTimeSpan = TimeSpan.FromDays(10),//access_token 过期时间
#if DEBUG
AllowInsecureHttp = true,
#endif
// Authorization server provider which controls the lifecycle of Authorization Server
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientAuthentication = ValidateClientAuthentication,
//这个方法就是后台处理密码模式认证关键的地方
OnGrantResourceOwnerCredentials= GrantResourceOwnerCredentials
}
});
}
///
/// ValidateClientAuthentication方法用来对third party application 认证,
/// 获取客户端的 client_id 与 client_secret 进行验证
/// context.Validated(); 表示允许此third party application请求。
///
///
///
private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId = null;
string clientSecret = null;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
context.TryGetFormCredentials(out clientId, out clientSecret))
{
if (clientId == "123456" && clientSecret == "abcdef")
{
context.Validated();
}
}
return Task.FromResult(0);
}
///
/// 这个方法就是后台处理密码模式认证关键的地方
/// 认证服务判断查询数据库判断该用户的用户名和密码是否正确。如果正确就会授权,产生token。
///
///
///
private async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (context.UserName != "qiuxianhu" || context.Password != "123456")
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
context.Rejected();
return;
}
else
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
var ticket = new AuthenticationTicket(claimsIdentity, new AuthenticationProperties());
context.Validated(ticket);
}
await Task.CompletedTask;
}
}
}(2)资源服务
(3)Client
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
namespace Client
{
class Program
{
static void Main(string[] args)
{
string server_url = "http://localhost:8063/";//认证服务地址
string resource_url = "http://localhost:8062/";//资源服务地址
string clientid = "123456";
string secret = "abcdef";
HttpClient _httpClient = new HttpClient();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("grant_type", "password");
parameters.Add("UserName", "qiuxianhu");
parameters.Add("Password", "123456");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes(clientid + ":" + secret))
);
var respOnse= _httpClient.PostAsync(new Uri(new Uri(server_url), "/Token"), new FormUrlEncodedContent(parameters)).Result;
var respOnseValue= response.Content.ReadAsStringAsync().Result;
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string token = JObject.Parse(responseValue)["access_token"].Value<string>();
Console.WriteLine(token);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Console.WriteLine(_httpClient.GetAsync(new Uri(new Uri(resource_url), "/api/values")).Result.Content.ReadAsStringAsync().Result);
}
Console.ReadKey();
}
}
}四、OWIN实现OAuth 2.0 之授权码模式
1、原理
2、示例
(1)认证服务
using Owin;
[assembly: OwinStartup(typeof(CodeService.Startup))]
namespace CodeService
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.COOKIEs;
using Microsoft.Owin.Security.Infrastructure;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace CodeService
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// 使应用程序可以使用 COOKIE 来存储已登录用户的信息
// 并使用 COOKIE 来临时存储有关使用第三方登录提供程序登录的用户的信息
// 配置登录 COOKIE
app.UseCOOKIEAuthentication(new COOKIEAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCOOKIE,
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString("/Account/Login"),
LogoutPath = new PathString("/Account/LoginOut"),
});
// Setup Authorization Server
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = new PathString("/OAuth/Authorize"),// AuthorizeEndpointPath是授权终结点,这个需要自己去写实现逻辑
TokenEndpointPath = new PathString("/OAuth/Token"),//TokenEndpointPath是生成Token的终结点,这个不需要我们写额外的逻辑了,因为Token的生成涉及到很多方面,例如序列化反序列加密解密等逻辑,所以框架默认已经帮我们做好了。
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
ApplicationCanDisplayErrors = true,
#if DEBUG
AllowInsecureHttp = true,//重要!!AllowInsecureHttp设置整个通信环境是否启用ssl,不仅是OAuth服务端,也包含Client端(当设置为false时,若登记的Client端重定向url未采用https,则不重定向)。
#endif
// Provider里面是用来验证客户端跳转地址和客户端验证,正确的做法应该是先判断客户端发送过来的ClientID是否合法,如果合法则验证通过。
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication
},
// Authorization code provider which creates and receives authorization code
AuthorizatiOnCodeProvider= new AuthenticationTokenProvider
{
OnCreate = CreateAuthenticationCode,
OnReceive = ReceiveAuthenticationCode,
},
// Refresh token provider which creates and receives referesh token
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
}
});
}
///
/// 客户端发送到授权终结点的请求是会被OWIN截取跳转到注册的 OnValidateClientRedirectUri委托,
/// 客户端发送授权请求代码:
/// var userAuthorization = _webServerClient.PrepareRequestUserAuthorization();
/// userAuthorization.Send(HttpContext);
/// Response.End();
///
///
///
private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
context.Validated();
return Task.FromResult(0);
}
///
/// TryGetBasicCredentials:是指Client可以按照Basic身份验证的规则提交ClientId和ClientSecret
/// TryGetFormCredentials:是指Client可以把ClientId和ClientSecret放在Post请求的form表单中提交
///
///
///
private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
context.TryGetFormCredentials(out clientId, out clientSecret))
{
if (clientId == "123456" && clientSecret == "abcdef")
{
context.Validated();
}
}
return Task.FromResult(0);
}
private readonly ConcurrentDictionary<string, string> _authenticatiOnCodes=
new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
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 void CreateRefreshToken(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
}
private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
}
using DotNetOpenAuth.OAuth2;
using System;
using System.Net.Http;
using System.Web.Mvc;
namespace ClientMvc.Controllers
{
public class HomeController : Controller
{
static string accessToken = null;
static string refreshToken = null;
public ActionResult Index()
{
Uri authorizatiOnServerUri= new Uri("http://localhost:8064/");//认证服务
AuthorizationServerDescription authorizatiOnServerDescription= new AuthorizationServerDescription
{
AuthorizatiOnEndpoint= new Uri(authorizationServerUri, "OAuth/Authorize"),
TokenEndpoint = new Uri(authorizationServerUri, "OAuth/Token")
};
WebServerClient webServerClient = new WebServerClient(authorizationServerDescription, "123456", "abcdef");
if (string.IsNullOrEmpty(accessToken))
{
IAuthorizationState authorizatiOnState= webServerClient.ProcessUserAuthorization(Request);
if (authorizationState != null)
{
accessToken = authorizationState.AccessToken;
refreshToken = authorizationState.RefreshToken;
}
}
// 授权申请
if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestAuthorize")))
{
//这里 new[] { "scopes1", "scopes2" }为需要申请的scopes,或者说是Resource Server的接口标识,或者说是接口权限。然后Send(HttpContext)即重定向。
OutgoingWebResponse grantRequest = webServerClient.PrepareRequestUserAuthorization(new[] { "scopes1", "scopes2" });
grantRequest.Send(HttpContext);
Response.End();
}
// 申请资源
if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestResource")))
{
var resourceServerUri = new Uri("http://localhost:8062/");//资源服务
var resourceRequest = new HttpClient(webServerClient.CreateAuthorizingHandler(accessToken));
ViewBag.ResourceRespOnse= resourceRequest.GetStringAsync(new Uri(resourceServerUri, "api/Values")).Result;
}
return View();
}
}
}
认证页面
@foreach (var scope in ViewBag.Scopes)
{
}
using Microsoft.Owin.Security;
using System.Security.Claims;
using System.Web;
using System.Web.Mvc;
namespace CodeService.Controllers
{
public class AccountController : Controller
{
public ActionResult Login()
{
if (Request.HttpMethod == "POST")
{
IAuthenticationManager authentication = HttpContext.GetOwinContext().Authentication;
// 默认用户登录成功,生产环境需要单独整合第三方登录信息
var username = Request.Form["username"];
var password = Request.Form["password"];
if (username == "qiuxianhu" && password == "123456")
{
authentication.SignIn(
new AuthenticationProperties { IsPersistent = true },
new ClaimsIdentity(new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, username) }, DefaultAuthenticationTypes.ApplicationCOOKIE)
);
var ticket = authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCOOKIE).Result;
}
}
return this.View();
}
public ActionResult Logout()
{
IAuthenticationManager authenticatiOnManager= HttpContext.GetOwinContext().Authentication;
authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCOOKIE);
return View();
}
}
}
ViewBag.Title = "Login";
}
ViewBag.Title = "Logout";
}Logout
(2)资源服务
(3)客户端
using DotNetOpenAuth.OAuth2;
using System;
using System.Net.Http;
using System.Web.Mvc;
namespace ClientMvc.Controllers
{
public class HomeController : Controller
{
static string accessToken = null;
static string refreshToken = null;
public ActionResult Index()
{
Uri authorizationServerUri = new Uri("http://localhost:8064/");//认证服务
AuthorizationServerDescription authorizatiOnServerDescription= new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri(authorizationServerUri, "OAuth/Authorize"),
TokenEndpoint = new Uri(authorizationServerUri, "OAuth/Token")
};
WebServerClient webServerClient = new WebServerClient(authorizationServerDescription, "123456", "abcdef");
if (string.IsNullOrEmpty(accessToken))
{
IAuthorizationState authorizationState = webServerClient.ProcessUserAuthorization(Request);
if (authorizationState != null)
{
accessToken = authorizationState.AccessToken;
refreshToken = authorizationState.RefreshToken;
}
}
// 授权申请
if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestAuthorize")))
{
//这里 new[] { "scopes1", "scopes2" }为需要申请的scopes,或者说是Resource Server的接口标识,或者说是接口权限。然后Send(HttpContext)即重定向。
OutgoingWebResponse grantRequest = webServerClient.PrepareRequestUserAuthorization(new[] { "scopes1", "scopes2" });
grantRequest.Send(HttpContext);
Response.End();
}
// 申请资源
if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestResource")))
{
var resourceServerUri = new Uri("http://localhost:8062/");//资源服务
var resourceRequest = new HttpClient(webServerClient.CreateAuthorizingHandler(accessToken));
ViewBag.ResourceResponse = resourceRequest.GetStringAsync(new Uri(resourceServerUri, "api/Values")).Result;
}
return View();
}
}
}
"http://www.w3.org/1999/xhtml">
"form1" method="POST">
"Authorize" name="btnRequestAuthorize" value="向认证服务器索要授权" type="submit" />
"Resource" name="btnRequestResource" value="访问资源(Resource)" type="submit" />