一步步搭建最簡單author2.0認證服務
oauth2.0 最早接觸這個概念是在做微信訂閱號開發。當時還被深深的繞進去,關於oauth2.0的解釋網上有好多,而且都講解的比較詳細,下面給大家價格參考資料。
http://owin.org/
http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/
http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katana
http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
http://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detection
http://msdn.microsoft.com/en-us/library/ff359101.aspx
接下來用最簡短的代碼實現author認證和授權。我們也可以先實現簡單案例,在理解。
這裏我以客戶端模式為例。
1.ASP.NET MVC 4 Web API 項目或者MVC5
2. 添加引用
Owin.dll
Microsoft.Owin.dll
Microsoft.Owin.Host.SystemWeb.dll
Microsoft.Owin.Security.dll
Microsoft.Owin.Security.Oauth.dll
Microsoft.Owin.Security.Cookies.dll
MicrosoftAspNet.Identity.Owin.dll
3.修改 App_Start 文件夾下面 Startup.Auth.cs文件,把原來自動生成那些東西全部去掉。
public void ConfigureAuth(Owin.IAppBuilder app){
var OauthOptions = new Microsoft.Owin.Securtity.Oauth.OAuthAuthorizationServerOptions{
AllowInsecureHttp = true,
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
//獲取 access_token 授權服務請求地址
TokenEndpointPath = new Microsoft.Owin.PathString("/token"),
//獲取 authorization_code 授權服務請求地址
AuthorizeEndpointPath = new Microsoft.Owin.PathString("/authorize"),
//access_token 過期時間
AccessTokenExpireTimeSpan = TimeSpan.FromSeconds(990),
//access_token 相關授權服務
Provider = new OpenAuthorizationServerProvider(),
//authorization_code 授權服務
RefreshTokenProvider = new OpenRefreshTokenProvider() //refresh_token 授權服務
};
app.UseOAuthBearerTokens(OAuthOptions);
}
修改Startup.cs 文件
[assembly: OwinStartup(typeof(WebApplication2.Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var configuration = new HttpConfiguration();
WebApiConfig.Register(configuration);
app.UseWebApi(configuration);
}
}
上面這個文件的作用 相當於 Global.asax文件,在程序啟動是及執行。
5. 新建 OpenAuthorizationServerProvider.cs 文件
public class OpenAuthorizationServerProvider :Microsoft.Owin.Security.OAuth.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);
}
//對clientId 和 clientSecret 經行驗證
context.Validated();
}
/// <summary>
/// 生成 access_token(client credentials 授權方式)
/// </summary>
public override async Task GrantClientCredentials(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);
}
}
6.新建 OpenRefreshTokenProvider.cs 文件
public class OpenRefreshTokenProvider: AuthenticationTokenProvider
{
private static ConcurrentDictionary<string, string> _refreshTokens = new ConcurrentDictionary<string, string>();
/// <summary>
/// 生成 refresh_token
/// </summary>
public override void Create(AuthenticationTokenCreateContext context)
{
context.Ticket.Properties.IssuedUtc = DateTime.UtcNow;
context.Ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddDays(60);
context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
_refreshTokens[context.Token] = context.SerializeTicket();
}
/// <summary>
/// 由 refresh_token 解析成 access_token
/// </summary>
public override void Receive(AuthenticationTokenReceiveContext context)
{
string value;
if (_refreshTokens.TryRemove(context.Token, out value))
{
context.DeserializeTicket(value);
}
}
}
修改ValuesControl.cs
public class ValuesController : ApiController
{
[Authorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
到這裏整個author2.0 客戶端模式 服務就待建好了。發布項目,這裏發布地址我們定義:http://192.168.1.147:87。接下來我們搭建測試端。
7.新建 “控制臺應用程序”。
8.新建 TokenResponse.cs 實體類。
public class TokenResponse
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int expires_in { get; set; }
}
修改 Program.cs
static void Main(string[] args) {
Program p = new Program();
string result = p.Request_WebRequest("http://192.168.1.147:87/token", "ceshi", "123456", 500000);
}
public string Request_WebRequest(string uri, string username, string password, int timeout)
{
string result = string.Empty;
WebRequest request = WebRequest.Create(new Uri(uri));
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
{
request.Credentials = GetCredentialCache(new Uri(uri), username, password);
request.Headers.Add("Authorization", GetAuthorization(username, password));
}
if (timeout > 0)
request.Timeout = timeout;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
ASCIIEncoding asciiEncode = new ASCIIEncoding();
byte[] data = asciiEncode.GetBytes("grant_type=client_credentials");
request.ContentLength = data.Length;
Stream newStream = request.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
result = sr.ReadToEnd();
TokenResponse tokenRes =Newtonsoft.Json.JsonConvert.DeserializeObject<TokenResponse>(result);
request = WebRequest.Create(new Uri("http://192.168.1.147:87/api/values"));
string rha = "Bearer " + tokenRes.AccessToken;
request.Headers.Add("Authorization",rha);
request.Method = "Get";
response = request.GetResponse();
stream = response.GetResponseStream();
sr = new StreamReader(stream);
result = sr.ReadToEnd();
sr.Close();
stream.Close();
return result;
}
private static CredentialCache GetCredentialCache(Uri uri, string username, string password)
{
string authorization = string.Format("{0}:{1}", username, password);
CredentialCache credCache = new CredentialCache();
credCache.Add(uri, "Basic", new NetworkCredential(username, password));
return credCache;
}
private static string GetAuthorization(string username, string password)
{
string authorization = string.Format("{0}:{1}", username, password);
return "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(authorization));
}
運行測試,
得到["value1","value2"]
得到預期結果。
一步步搭建最簡單author2.0認證服務