我是基於令牌的身份驗證的新手,我登錄後如何維護登錄狀態。 我想創建一個SPA網站,我正在使用Knockoutjs爲我的前端和SammyJS進行路由和更改視圖。 我登錄並獲取令牌後,將其存儲在localStorage中,並將用戶名設置爲我正在顯示的可觀察值。KnockoutJS + WebAPI 2令牌身份驗證 - 保持登錄狀態,直到令牌過期
我的問題是,關閉標籤頁或瀏覽器後,我回到網站,令牌是在localStorage,但我看不到用戶登錄。 我想保持登錄狀態,直到令牌到期。我的問題是,當我進入網站以維護該用戶的登錄狀態時,我應該如何處理來自localStorage的令牌?
我需要在啓動類中做些什麼或檢查數據庫中是否存在該用戶?
提前致謝!
這裏是我的代碼:
StartupAuth.cs
[assembly: OwinStartup(typeof(EventHub.PL.WebUI.Startup))] namespace EventHub.PL.WebUI {
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get;private set; }
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
public const string TokenEndpointPath = "/api/token";
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString(TokenEndpointPath),
Provider = new ApplicationOAuthProvider(PublicClientId),
//AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
//app.UseOAuthBearerTokens(OAuthOptions);
app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
}
}
AccountController.cs
[HttpPost]
[AllowAnonymous]
[Route("Login")]
public async Task<IHttpActionResult> Login(LoginUser model)
{
var request = HttpContext.Current.Request;
var tokenServiceUrl = request.Url.GetLeftPart(UriPartial.Authority) + request.ApplicationPath + "/api/Token";
using (var client = new HttpClient())
{
var requestParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", model.Email),
new KeyValuePair<string, string>("password", model.Password)
};
var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
var tokenServiceResponse = await client.PostAsync(tokenServiceUrl, requestParamsFormUrlEncoded);
var responseString = await tokenServiceResponse.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<TokenResponse>(responseString);
var responseCode = tokenServiceResponse.StatusCode;
if (responseCode == HttpStatusCode.OK)
{
RegisterUser user = userRepository.GetNameById(json.Id);
var data = new
{
status = "success",
json.access_token,
user.Lastname
};
return Json(data);
}
return Json(new { status = "failed" });
}
}
這裏是KO部分:
var LoginApp = function() {
var instance = this;
instance.mainViewModel = new MainViewModel();
instance.loginViewModel = new LoginViewModel();
instance.loginRepository = new LoginRepository();
instance.loginViewModel.signIn = function() {
$('.loader-header').show();
var postData = {
email: instance.loginViewModel.email(),
password: instance.loginViewModel.password
}
instance.loginRepository.SignIn(SignInSuccess, postData);
};
instance.SignInSuccess = function(response) {
if (response.status === 'success') {
instance.mainViewModel.username(response.Lastname);
instance.mainViewModel.isVisible(true);
var userData = {
token: response.access_token,
username: response.Lastname
};
localStorage.setItem('AuthorizationData', JSON.stringify(userData));
$('.loader-header').hide();
dialog.close();
} else {
$('.loader-header').hide();
}
};
instance.init = function() {
ko.applyBindings(instance.loginViewModel, document.getElementById("signin-form"));
ko.applyBindings(instance.mainViewModel, document.getElementById("main-wrapper"));
}
instance.init();
}
$(document).ready(function() {
var loginApp = LoginApp();
});
UPDATE
這裏是我的路由還
var appRoot = root;
(function ($) {
var app = $.sammy('#page', function() {
this.get('#/home', function (context) {
document.title = 'Home - ' + title;
var url = getUrlFromHash(context.path);
loadView(url, new MainViewModel(), MainApp);
//context.load(url).swap();
});
this.get('#/about', function (context) {
var url = getUrlFromHash(context.path);
loadView(url, new AboutViewModel(), AboutApp);
});
this.get('#/manage', function (context) {
var url = getUrlFromHash(context.path);
loadView(url, new AboutViewModel(), AboutApp);
});
});
$(function() {
app.run('#/home');
});
})(jQuery);
function loadView(url, viewModel, callback) {
$.get(url, function (response) {
var $container = $('#page');
//var $view = $('#page').html(response);
$container.html(response);
callback();
});
}
function getUrlFromHash(hash) {
var url = hash.replace('#/', '');
if (url === appRoot)
url = 'home';
return url;
}
感謝您的回覆,我使用登錄從彈出窗口發送給控制器,'#/ oauth/login'是通往控制器的路由,對不對?我需要在'主頁'路線上進行檢查,對吧?這有點不清楚。 –
這是正確的 - 在第一個片段中,您通過POST請求向「#/ oauth/login」發送'email'和'password'給服務器(即Wep API控制器)。第二個片段定義了一個路由,用於檢查用戶是否已經過身份驗證。如果是這種情況,那麼用戶被引導到期望的頁面(即「view/profile.template」) –
好的,謝謝!還有一件事,我可以使用按鈕上的第一個片段來將它發送給控制器?因爲對於登錄/註冊,我不使用任何類似於其他頁面的URL(#/ about),它只是一個彈出窗口,並且在按鈕上我將數據發送到控制器。所以我不太清楚如何使用這種方法。就像我張貼網站的路由部分,而不是讓我使用後?提前致謝! –