public void ConfigureAuth(IAppBuilder app) { // 設定資料庫內容和使用者管理員以針對每個要求使用單一執行個體 app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); // 讓應用程式使用 Cookie 儲存已登入使用者的資訊 // 並使用 Cookie 暫時儲存使用者利用協力廠商登入提供者登入的相關資訊; app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // 設定 OAuth 基礎流程的應用程式 PublicClientId = "self"; OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), // 在生產模式中設定 AllowInsecureHttp = false AllowInsecureHttp = true }; // 讓應用程式使用 Bearer 權杖驗證使用者 app.UseOAuthBearerTokens(OAuthOptions); }得知 OAuthAuthorizationServerOptions.Provider 使用 ApplicationOAuthProvider, 想要在取 token 所回傳的 json 中加入其他資料(例如 name 和 city), 因此針對他的 GrantResourceOwnerCredentials 方法進行修改 :
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { await Task.Run(() => { // 自行驗證 if (context.UserName == "ian" && context.Password == "1111") { // 驗證通過 // 建立一個 ClaimsIdentity var identity = new ClaimsIdentity(context.Options.AuthenticationType); // 加入一些自行命名且好讀的 Claim identity.AddClaim(new Claim("name", "Ian")); identity.AddClaim(new Claim("city", "Tainan")); // 建立一個 AuthenticationProperties var p1 = new Dictionary<string, string> { {"name","Ian"}, // 顯示於回傳的json中 {"city","Tainan"} }; AuthenticationProperties properties = new AuthenticationProperties(p1); // 使用 ClaimsIdentity 和 AuthenticationProperties 來產生一個 AuthenticationTicket AuthenticationTicket ticket = new AuthenticationTicket(identity, properties); // 替換此內容上的票證資訊,並讓其由應用程式驗證。 呼叫之後,IsValidated 為 true 且 HasError 為 false。 context.Validated(ticket); context.Request.Context.Authentication.SignIn(identity); } else { context.SetError("invalid_grant", "使用者名稱或密碼不正確。"); return; } }); }
測試 :
使用 jQuery.ajax 取 Token :
$.ajax({ url: '/token', data: { username: username, password: password, grant_type: 'password' }, type: 'POST', success: function (data) { console.log(data); $('#token').val(data.access_token); } });
結果 :
{"access_token":"F5PU_EhpbLl7aw_EwlTuP8unNXc4L9olOlqbuan0oQbjPyh-u5iEUjQnRcs7AkV6ia7clMPn8JyZZxNucD5mP_vUTvmeGjDGZJI33qzWzehGP4xQr5HCMQ0EtaCBi7pxq0WttOtLYumoZNXmBDnRWqTtn3s7iBszewS1IHb__J2-zd1nzVmT7VKOVe_GFQhKCB_cXMqCPyfPaERLrzBYjT3ju3RYIrDn1m-ZuaLXwVM","token_type":"bearer","expires_in":1209599,"name":"Ian","city":"Tainan",".issued":"Wed, 02 Sep 2015 07:33:46 GMT",".expires":"Wed, 16 Sep 2015 07:33:46 GMT"}
name 和 city 被加入到回傳的 json 中
在後端程式中使用 ClaimsIdentity 中的資料, 例如取得使用者的 city :
[Authorize] public class UserCityController : ApiController { public string Get() { var identity = User.Identity as ClaimsIdentity; var city = (identity.Claims).Where(x => x.Type == "city").Select(x => x.Value).FirstOrDefault(); return city; } }
前端使用 jQuery 撈取 :
$.ajax({ url: '/api/usercity', type: 'GET', headers: { 'Authorization': 'Bearer ' + $('#token').val() }, success: function (data) { $('#user-city').text(data); } });Authorization : Bearer {token}
沒有留言:
張貼留言