Je veux créer un exemple d'authentification et d'autorisation dans une application SPA angularjs utilisant asp.net mvc webapi comme backend et routage côté client (pas de cshtml). Voici un exemple de fonctions qui peuvent être utilisées pour configurer l'exemple complet. Mais je ne peux pas tout mettre ensemble. Toute aide appréciée.
Des questions:
Exemple de code:
Formulaire de connexion
<form name="form" novalidate>
<input type="text" ng-model="user.userName" />
<input type="password" ng-model="user.password" />
<input type="submit" value="Sign In" data-ng-click="signin(user)">
</form>
Authentification Angular
$scope.signin = function (user) {
$http.post(uri + 'account/signin', user)
.success(function (data, status, headers, config) {
user.authenticated = true;
$rootScope.user = user;
$location.path('/');
})
.error(function (data, status, headers, config) {
alert(JSON.stringify(data));
user.authenticated = false;
$rootScope.user = {};
});
};
Mon code API backend API.
[HttpPost]
public HttpResponseMessage SignIn(UserDataModel user)
{
//FormsAuthetication is just an example. Can I use OWIN Context to create a session and cookies or should I just use tokens for authentication on each request? How do I preserve the autentication signed in user on the client?
if (this.ModelState.IsValid)
{
if (true) //perform authentication against db etc.
{
var response = this.Request.CreateResponse(HttpStatusCode.Created, true);
FormsAuthentication.SetAuthCookie(user.UserName, false);
return response;
}
return this.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Invalid username or password");
}
return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState);
}
Autorisation Utilisation de la bibliothèque JWT pour restreindre le contenu.
config.MessageHandlers.Add(new JsonWebTokenValidationHandler
{
Audience = "123",
SymmetricKey = "456"
});
Mes méthodes API
[Authorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
L'utilisation de l'authentification par cookie ou des jetons (au porteur) dépend toujours du type d'application que vous avez. Et pour autant que je sache, il n'y a pas encore de meilleure pratique. Mais puisque vous travaillez sur un SPA et que vous utilisez déjà une bibliothèque JWT, je préférerais l'approche basée sur les jetons.
Malheureusement, je ne peux pas vous aider avec ASP.NET, mais généralement les bibliothèques JWT génèrent et vérifient le jeton pour vous. Tout ce que vous avez à faire est d'appeler generate
ou encode
sur les informations d'identification (et le secret) et verify
ou decode
sur le jeton envoyé avec chaque demande. Et vous n'avez pas besoin de stocker un état sur le serveur et vous n'avez pas besoin d'envoyer un cookie, ce que vous avez probablement fait avec FormsAuthentication.SetAuthCookie(user.UserName, false)
.
Je suis sûr que votre bibliothèque fournit un exemple sur la façon d'utiliser les jetons de génération/codage et de vérification/décodage.
La génération et la vérification ne sont donc pas quelque chose que vous faites du côté client.
Le flux va quelque chose comme ceci:
Étape 1 et 3:
app.controller('UserController', function ($http, $window, $location) {
$scope.signin = function(user) {
$http.post(uri + 'account/signin', user)
.success(function (data) {
// Stores the token until the user closes the browser window.
$window.sessionStorage.setItem('token', data.token);
$location.path('/');
})
.error(function () {
$window.sessionStorage.removeItem('token');
// TODO: Show something like "Username or password invalid."
});
};
});
sessionStorage
conserve les données tant que l'utilisateur a la page ouverte. Si vous souhaitez gérer vous-même les délais d'expiration, vous pouvez utiliser localStorage
à la place. L'interface est la même.
Étape 4:
Pour envoyer le token à chaque requête au serveur, vous pouvez utiliser ce que Angular appelle un Interceptor . Tout ce que vous avez à faire est d'obtenir le token précédemment stocké (le cas échéant) ) et le joindre en tant qu'en-tête à toutes les demandes sortantes:
app.factory('AuthInterceptor', function ($window, $q) {
return {
request: function(config) {
config.headers = config.headers || {};
if ($window.sessionStorage.getItem('token')) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.getItem('token');
}
return config || $q.when(config);
},
response: function(response) {
if (response.status === 401) {
// TODO: Redirect user to login page.
}
return response || $q.when(response);
}
};
});
// Register the previously created AuthInterceptor.
app.config(function ($httpProvider) {
$httpProvider.interceptors.Push('AuthInterceptor');
});
Et assurez-vous de toujours utiliser SSL!