0

我是基於令牌的身份驗證的新手,我登錄後如何維護登錄狀態。 我想創建一個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; 
} 

回答

0

現在你正在做的是存儲用戶在localStorage的憑據,但不使用它們進行授權。另一種方法是使用Sammy.OAuth2插件(您可以找到它here)。

您可以定義一個路由,使像認證:

app.post("#/oauth/login", function(context) { 
    this.load('http://yourwebsite/login', 
     { 
      cache: false, 
      type: 'post', 
      data: { 
       email: $("input[name=email]").val(), 
       password: $("input[name=password]").val() 
      } 
     }) 
     .then(function(content) { 
      if(content != false){ 
       if(app.getAccessToken() == null){ 
        app.setAccessToken(token()); 
       } 
      }else{ 
       app.trigger("oauth.denied"); 
       return false; 
      } 
     }); 
}); 

在「保護」的路線,你可以檢查用戶是否已經登錄這樣的:

app.get("#/profile", function(context) { 

    if(app.getAccessToken() != null) 
     context.render('view/profile.template'); 
    else 
     this.requireOAuth(); 

}); 

這個例子必須根據您的方案進行修改以填充令牌。這裏有一個關於Sammy.Oath2的完整教程。

+0

感謝您的回覆,我使用登錄從彈出窗口發送給控制器,'#/ oauth/login'是通往控制器的路由,對不對?我需要在'主頁'路線上進行檢查,對吧?這有點不清楚。 –

+0

這是正確的 - 在第一個片段中,您通過POST請求向「#/ oauth/login」發送'email'和'password'給服務器(即Wep API控制器)。第二個片段定義了一個路由,用於檢查用戶是否已經過身份驗證。如果是這種情況,那麼用戶被引導到期望的頁面(即「view/profile.template」) –

+0

好的,謝謝!還有一件事,我可以使用按鈕上的第一個片段來將它發送給控制器?因爲對於登錄/註冊,我不使用任何類似於其他頁面的URL(#/ about),它只是一個彈出窗口,並且在按鈕上我將數據發送到控制器。所以我不太清楚如何使用這種方法。就像我張貼網站的路由部分,而不是讓我使用後?提前致謝! –