在 asp.net Web api 和 angular js 中使用的身份验证方法

Authentication approach to be use in asp.net Web api and angular js

我正在使用 Web api 和 angular js 创建 1 个网站,我对在我的网站中使用的身份验证感到非常困惑。

我创建了一个 login.js,其中包含我的登录方法,它将 post 我的 Username/Emailid 和我的 Web 的密码Api 和网络中的方法 api 将验证该用户。

代码:

$scope.Login()
{
  $.post("api/Authentication/Login",Username,Password)
  {
  }
}

网页api代码:

[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??
}

Darin Dimitrov 在他的回答和评论中指出,使用会话是一场灾难。 所以我决定根据这个答案和 Nop Commerce uses cookie too to store currently login customer object as per this question and answer Question

电子商务网站之一使用 cookie

我正在按照 LukeP in this Question 建议的代码进行身份验证,并在我的整个应用程序中维护当前登录用户对象。

我也读过 asp.net 声明身份,但不知道我是否可以在我的 asp.net 网络 api 和 angular js 中使用它。

谁能告诉我在 asp.net web api 和 angular js 中使用什么正确的身份验证方法以及在 [=18= 中要完成的所有更改] 使用 web api 和 angular js 的代码??

任何人都可以向我解释一下我在上面指出的这个方法以及一些详细描述和一些代码,因为它可以帮助我和其他一些人,如果他们正在搜索相同的东西。

稍后我将提供 100 赏金来解决上述所有问题,并提供一些代码。

这是一个非常宽泛的问题,不可能在单一答案中完成。

我能告诉你的是 "token authentication" 有了 Outh2 就可以了;当我们谈论安全性时,这是使用 Angular 和 WebAPI 的最简单方法。在这种情况下,Cookie 不是正确的解决方案。

查看 this 文章,了解有关如何使用 ASP.NET Web API 2、Owin 和 Identity 实现完整的基于令牌的身份验证的更多详细信息。那篇文章在很多方面确实帮助了我。最终,当你有一个示例解决方案时,你可以回到这里并要求更多 "details".

顺便说一句,我在你的代码中读到了这个 "comment":

//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

就我个人而言,我认为会话是邪恶的。我不是唯一的 one。 反正你要在web.api世界里用"session",不是免费出来的,得激活才行。因此,如果出于任何原因您需要使用它,请检查 this.

希望对您有所帮助:)

最好的方法是使用 json 网络令牌 (JWT)...

Satellizer 是一个很棒的库,可以添加到您的 Angular 应用中 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);
          });
        };    
  });

服务器端,他们在 https://github.com/sahat/satellizer/tree/master/examples/server/c%23

有一个 C# 示例

最好的方法是使用令牌身份验证。总之它是这样工作的:

  • 服务器上的POST /api/login路由接受用户名+密码,检查它们对数据库是否有效,然后生成returns一个refresh token(可以是随机字符串或 GUID)。 refresh token也存储在用户旁边的数据库中,覆盖之前的refresh token
  • 服务器上的 GET /api/access-token 路由接受用户名 + refresh token,检查它们在数据库中是否匹配,然后生成 returns 一个 access token
  • 任何其他 /api/* 路由需要有效的 access token 才能在请求的 header 中,否则它们会假定用户没有有效的登录名

access token 是一个数据object,使用只有服务器知道的密钥加密。它应该包含用户名、到期日期(通常是令牌生成后约 10 分钟)以及有关用户的任何权限或杂项数据。因为它是用密钥加密的,所以不能被攻击者伪造。

您需要在您的服务器上实现这些路由。

如果您使用的是 OWIN,可以通过以下方式使用 Microsoft.Owin.Security.OAuth NuGet 包为您进行加密:

在你的启动配置中有这个:

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);
        }
    }
}

然后,您可以生成一个ticket(即未加密的access token)并像这样加密它:

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);

在 Angular 中,您需要设置一种登录方式,一种在过期时获取新 access token 的方式,以及一种在 [=] 中传递 access token 的方式每个 API 请求的 64=]。我建议将 refresh tokenaccess token 存储在本地存储(或旧浏览器的 cookie)中,并使用 $httpProvider.interceptors.push 为每个 $http 调用添加一个拦截器。然后拦截器可以像这样将访问令牌添加到 header:config.headers['Authorization'] = 'Bearer ' + accessToken;

在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;
    };
}]);

将其添加到 $httpProvider:

angular.module('app').config(['$httpProvider', ($httpProvider: ng.IHttpProvider) => {
    $httpProvider.interceptors.push('authenticationInterceptor');
}]);