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

Правильно - в первом фрагменте вы отправляете «письмо» и «пароль» на сервер (т. Е. Контроллер API Wep) в запросе POST на «#/oauth/login». Второй фрагмент определяет маршрут, который проверяет, проверен ли пользователь уже. Если это так, то пользователь направляется на нужную страницу (т. Е. «View/profile.template») –

+0

Хорошо, спасибо! Еще одно, первый фрагмент, который я могу использовать при нажатии кнопки для отправки его на контроллер?Поскольку для входа/регистрации я не использую какой-либо URL-адрес, как для других страниц (#/about), это просто всплывающее окно, и на кнопке я отправляю данные на контроллер. Поэтому я не совсем уверен, как использовать этот подход. Что-то вроде того, что я разместил часть маршрутизации веб-сайта, но вместо того, чтобы использовать пост? Заранее спасибо! –