问题
I am creating 1 website using Web api and angular js and i am so much confused about Authentication to be used in my web site.
I have created one login.js in which there would be my Login method which will post my Username/Emailid and password to my Web Api and the method in web api will authenticate that user.
Code:
$scope.Login()
{
$.post("api/Authentication/Login",Username,Password)
{
}
}
Web api code:
[Route]
Public Task<object> Login([FromBody] username,password)
{
//method to authenticate user from database.
//Now the tricky parts comes like after authenticating user should i
//just store the user id in my session like this Session["userid]=id or
//Should i go for storing whole user object in my cookie as i have read
//that storing data in session is very bad idea and disaster too as session is very memory
//and so i think i would go for cookie which will be saved on client side.
//but what if cookie isnt supported by browser??
}
Using session is disaster as pointed out by Darin Dimitrov in his answer and comments. So i have decided to use cookie as per this answer and one of the ecommerce site that is Nop Commerce uses cookie too to store currently login customer object as per this question and answer Question
I am following this code suggested by LukeP in this Question for authentication purpose and maintaining currenlty login user object across my whole appilcation.
I have read about asp.net claim identity too but dont know whether i can use it in my asp.net web api and angular js.
So can anybody tell me whats the correct approach to use for authentication in asp.net web api and angular js and what all the changes to be done in LukeP code to work with web api and angular js??
Can anybody explain me about this appraoch which i have pointed above with some detail description and some codes too as it can help me and some others too if they are searching for the same.
Later i will offer 100 bounty to the answer addressing all above concern with some codes.
回答1:
The best way to do it is with token authentication. In summary it works like this:
- A
POST /api/login
route on the server takes in a username + password, checks that they are valid against the database, then generates and returns arefresh token
(which can just be a random string or GUID). Therefresh token
is also stored in the database next to the user, overwriting the previousrefresh token
- A
GET /api/access-token
route on the server takes in a username +refresh token
, checks that they match in the database, then generates and returns anaccess token
- Any other
/api/*
routes require a validaccess token
to be in the header of the request, otherwise they assume the user does not have a valid login
The access token
is a data object that has been encrypted using a secret key that only the server knows. It should contain the username, an expiry date (usually ~10mins from when the token was generated), and any permissions or misc data about the user. Because it is encrypted with a secret key, it cannot be forged by an attacker.
You will need to implement these routes on your server.
If you are using OWIN, here is how you can use the Microsoft.Owin.Security.OAuth
NuGet package to do the encryption bit for you:
Have this in your startup configuration:
using System.Web.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
[assembly: OwinStartup(typeof(MyProject.Startup))]
namespace MyProject
{
public class Startup
{
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
app.UseWebApi(config);
}
}
}
Then, you can generate a ticket
(which is the unencrypted access token
) and encrypt it like this:
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Email, "users email"),
// other business specific claims e.g. "IsAdmin"
});
var ticket = new AuthenticationTicket(identity, new AuthenticationProperties(
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(10)
}));
var accessToken = MyProject.Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
In Angular you need to setup a way to login, a way to get a new access token
when it expires, and a way to pass the access token
in the header of every API request. I recommend storing the refresh token
and access token
in local storage (or cookie for old browsers), and using $httpProvider.interceptors.push
to add an interceptor for every $http
call. The interceptor can then add the access token to the header like this: config.headers['Authorization'] = 'Bearer ' + accessToken;
Define the interceptor in angular:
angular.module('app').service('authenticationInterceptor', ['$q', function($q) {
this.request = function(config) {
var accessToken = // ... get the access token from local storage / cookie
config.headers['Authorization'] = 'Bearer ' + accessToken;
return config;
};
}]);
Add it to $httpProvider
:
angular.module('app').config(['$httpProvider', ($httpProvider: ng.IHttpProvider) => {
$httpProvider.interceptors.push('authenticationInterceptor');
}]);
回答2:
This is a very broad question to answer and there is no chance of doing it in single answer.
What I can say to you is "token authentication" with Outh2 should do the job; that's the easiest way to work with Angular and WebAPI when we talk about security. Cookies are not the right solution in this case.
Check this article for more details on how to implement a full working Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. That article really helped me in many ways. Eventually, when you will have a sample solution, you can came back here and ask for more "details".
BTW, I read this "comment" inside you code:
//Now the tricky parts comes like after authenticating user should i //just store the user id in my session like this Session["userid]=id or //Should i go for storing whole user object in my cookie as i have read
Personally, I think session is evil. I'm not the only one. Anyway, if you want to use "session" in web.api world, it doesn't come out for free, you have to activate it. So if for any reason you need to use it, check this.
Hope it helps :)
回答3:
The best way is to use json web token (JWT)...
Satellizer is a great library to add to your Angular app https://github.com/sahat/satellizer
HTML
<form method="post" ng-submit="login()" name="loginForm">
<div class="form-group has-feedback">
<input class="form-control input-lg" type="text" name="email" ng-model="user.email" placeholder="Email" required autofocus>
<span class="ion-at form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input class="form-control input-lg" type="password" name="password" ng-model="user.password" placeholder="Password" required>
<span class="ion-key form-control-feedback"></span>
</div>
<button type="submit" ng-disabled="loginForm.$invalid" class="btn btn-lg btn-block btn-success">Log in</button>
<br/>
<p class="text-center text-muted">
<small>Don't have an account yet? <a href="/#/signup">Sign up</a></small>
</p>
<div class="signup-or-separator">
<h6 class="text">or</h6>
<hr>
</div>
</form>
JS
angular.module('MyApp')
.controller('LoginCtrl', function($scope, $auth) {
$scope.login = function() {
$auth.login($scope.user)
.then(function() {
toastr.success('You have successfully signed in!');
$location.path('/');
})
.catch(function(error) {
toastr.error(error.data.message, error.status);
});
};
});
Server-side, they have a C# example at https://github.com/sahat/satellizer/tree/master/examples/server/c%23
来源:https://stackoverflow.com/questions/36102192/authentication-approach-to-be-use-in-asp-net-web-api-and-angular-js