Подход аутентификации для использования в asp.net Web api и angular js

Я создаю 1 веб-сайт, используя Web api и angular js, и я настолько смущен об аутентификации, которая будет использоваться на моем веб-сайте.

Я создал один login.js, в котором будет мой метод входа, который выведет мое имя пользователя/электронной почты и пароль на мой веб-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??
}

Использование сеанса - это катастрофа, о которой говорил Дарин Димитров в своем ответе и комментариях. Поэтому я решил использовать cookie в соответствии с этим ответом, и один из сайтов электронной торговли, который Nop Commerce использует cookie также для хранения в настоящее время объекта для входа в систему в соответствии с этим вопросом и ответом Вопрос

Я следую этому коду, предложенному LukeP в этом Question для целей аутентификации и поддерживая текущий пользовательский объект входа во всей моей appilcation.

Я тоже читал об идентификаторе претензии asp.net, но не знаю, могу ли я использовать его в моем asp.net web api и angular js.

Так может кто-нибудь сказать мне, какой правильный подход использовать для аутентификации в asp.net web api и angular js и что все изменения должны быть сделаны в LukeP для работы с web api и angular js??

Может кто-нибудь объяснить мне об этой оценке, которую я указал выше, с некоторым подробным описанием и некоторыми кодами, так как это может помочь мне и некоторым другим, если они ищут то же самое.

Позже я предложат 100 баунти ответу на все вышеперечисленные проблемы с некоторыми кодами.

Ответ 1

Лучший способ сделать это - проверить токен. В итоге он работает следующим образом:

  • A POST /api/login маршрут на сервере принимает имя пользователя + пароль, проверяет, что они действительны в отношении базы данных, затем генерирует и возвращает refresh token (который может быть просто случайной строкой или GUID). refresh token также сохраняется в базе данных рядом с пользователем, перезаписывая предыдущий refresh token
  • Маршрут A GET /api/access-token на сервере принимает имя пользователя + refresh token, проверяет, что они совпадают в базе данных, затем генерирует и возвращает access token
  • Любые другие маршруты /api/* требуют наличия правильного access token в заголовке запроса, в противном случае они предполагают, что у пользователя нет действительного входа

access token - это объект данных, который был зашифрован с использованием секретного ключа, который знает только сервер. Он должен содержать имя пользователя, дату истечения срока действия (обычно ~ 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. Я рекомендую хранить refresh token и access token в локальном хранилище (или файл cookie для старых браузеров) и использовать $httpProvider.interceptors.push для добавления перехватчика для каждого вызова $http. Затем перехватчик может добавить токен доступа в заголовок следующим образом: 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');
}]);

Ответ 2

Это очень широкий вопрос для ответа, и нет никаких шансов сделать это в одном ответе.

То, что я могу сказать вам, - это "аутентификация токена" с помощью Outh2, должна выполнять эту работу; что самый простой способ работы с Angular и WebAPI, когда мы говорим о безопасности. В этом случае Cookies не являются правильным решением.

Отметьте эту статью для получения дополнительной информации о том, как реализовать полную рабочую аутентификацию на основе токенов с использованием ASP.NET Web API 2, Owin и Identity, Эта статья действительно помогла мне во многих отношениях. В конце концов, когда у вас будет образец решения, вы можете вернуться сюда и попросить более подробную информацию.

Кстати, я прочитал этот "комментарий" внутри вашего кода:

//Теперь сложная часть приходит, как после аутентификации пользователя. я    // просто сохраняем идентификатор пользователя в моей сессии, как этот сеанс ["userid] = id или    // Должен ли я продолжать хранить весь пользовательский объект в своем cookie, как я читал

Лично я считаю, что сессия зла. Я не единственный один. В любом случае, если вы хотите использовать "сеанс" в мире web.api, он не выходит бесплатно, вы должны его активировать. Поэтому, если по какой-либо причине вам необходимо использовать его, отметьте this.

Надеюсь, это поможет:)

Ответ 3

Лучший способ - использовать json web-токен (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