AngularJS : 단일 페이지 애플리케이션에서 인증을 사용하는 기본 예제


100

저는 AngularJS를 처음 했고 그들의 튜토리얼을 살펴보고 그것에 대한 느낌을 받았습니다.

REST엔드 포인트를 인증해야하는 프로젝트에 대한 백엔드가 준비 되어 있습니다.

내가하고 싶은 일
a.) 내 프로젝트를위한 단일 페이지를 갖고 싶습니다 http://myproject.com.
b.) 사용자가 브라우저에서 URL을 클릭하면 사용자가 로그인했는지 여부에 따라 동일한 URL 아래에 홈 페이지 /보기 또는 로그인 페이지 /보기가 표시됩니다 http://myproject.com.
c.) 사용자가 로그인하지 않은 경우 양식을 작성하고 서버 USER_TOKEN에서 세션을 설정 하므로 엔드 포인트에 대한 모든 추가 요청은 다음을 기반으로 인증됩니다.USER_TOKEN

내 혼란
a.) AngularJS를 사용하여 클라이언트 측 인증을 어떻게 처리 할 수 ​​있습니까? 나는보고 여기여기에 있지만 사용하는 방법을 이해하지 못했다
B를.) 사용자 또는하지 동일한 URL에서 로그인 한 경우에 사용자에게 나는 현재 다른 뷰를 기반으로 수있는 방법http://myproject.com

나는 angular.js를 처음으로 사용하고 있으며 시작하는 방법에 대해 정말로 혼란스러워합니다. 모든 조언 및 / 또는 리소스는 대단히 감사합니다.


아래 기사를보십시오 frederiknakstad.com/…
Ajay Beniwal 2013-04-22

1
@MichaelCalkins는 단지 링크를 배치하는 것은 건설적이지 않습니다. 적어도 링크가 제공 할 내용을 말해야합니다.
Dave Gordon

내 b : AngularJS 액세스 제어 및 인증 coderwall.com/p/f6brkg
Michael J. Calkins

답변:


48

이 기사를 기본적으로 요약 한 github 저장소를 만들었습니다. https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

ng-login Github 저장소

플 런커

가능한 한 잘 설명하려고 노력하겠습니다. 여러분 중 일부를 돕길 바랍니다.

(1) app.js : 앱 정의에 대한 인증 상수 생성

var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
    all : '*',
    admin : 'admin',
    editor : 'editor',
    guest : 'guest'
}).constant('AUTH_EVENTS', {
    loginSuccess : 'auth-login-success',
    loginFailed : 'auth-login-failed',
    logoutSuccess : 'auth-logout-success',
    sessionTimeout : 'auth-session-timeout',
    notAuthenticated : 'auth-not-authenticated',
    notAuthorized : 'auth-not-authorized'
})

(2) Auth 서비스 : auth.js 서비스에서 다음의 모든 기능이 구현됩니다. $ http 서비스는 인증 절차를 위해 서버와 통신하는 데 사용됩니다. 또한 사용자가 특정 작업을 수행 할 수있는 권한 부여 기능도 포함합니다.

angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS', 
function($http, $rootScope, $window, Session, AUTH_EVENTS) {

authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]

return authService;
} ]);

(3) 세션 : 사용자 데이터를 보관하는 싱글 톤입니다. 여기의 구현은 사용자에 따라 다릅니다.

angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {

    this.create = function(user) {
        this.user = user;
        this.userRole = user.userRole;
    };
    this.destroy = function() {
        this.user = null;
        this.userRole = null;
    };
    return this;
});

(4) 상위 컨트롤러 : 이를 애플리케이션의 "주요"기능으로 간주하고 모든 컨트롤러는이 컨트롤러에서 상속되며이 앱 인증의 중추입니다.

<body ng-controller="ParentController">
[...]
</body>

(5) 액세스 제어 : 특정 경로에서 액세스를 거부하려면 2 단계를 구현해야합니다.

a) 아래에서 볼 수 있듯이 ui 라우터의 $ stateProvider 서비스에서 각 경로에 액세스 할 수있는 역할의 데이터를 추가합니다 (ngRoute에서도 동일하게 작동 할 수 있음).

.config(function ($stateProvider, USER_ROLES) {
  $stateProvider.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/index.html',
    data: {
      authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
    }
  });
})

b) $ rootScope. $ on ( '$ stateChangeStart')에서 사용자에게 권한이없는 경우 상태 변경을 방지하는 함수를 추가합니다.

$rootScope.$on('$stateChangeStart', function (event, next) {
    var authorizedRoles = next.data.authorizedRoles;
    if (!Auth.isAuthorized(authorizedRoles)) {
      event.preventDefault();
      if (Auth.isAuthenticated()) {
        // user is not allowed
        $rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
      } else {
        // user is not logged in
        $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
      }
    }
});

(6) 인증 인터셉터 : 구현되었지만이 코드의 범위에서 확인할 수 없습니다. 각 $ http 요청 후이 인터셉터는 상태 코드를 확인하고, 아래 중 하나가 반환되면 이벤트를 브로드 캐스트하여 사용자가 다시 로그인하도록합니다.

angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
    return {
        responseError : function(response) {
            $rootScope.$broadcast({
                401 : AUTH_EVENTS.notAuthenticated,
                403 : AUTH_EVENTS.notAuthorized,
                419 : AUTH_EVENTS.sessionTimeout,
                440 : AUTH_EVENTS.sessionTimeout
            }[response.status], response);
            return $q.reject(response);
        }
    };
} ]);

PS 첫 번째 기사에 언급 된 양식 데이터 자동 완성 버그는 directives.js에 포함 된 지시문을 추가하여 쉽게 피할 수 있습니다.

PS2 이 코드는 사용자가 쉽게 조정할 수있어 다른 경로를 보거나 표시 할 의도가없는 콘텐츠를 표시 할 수 있습니다. 로직은 반드시 서버 측에서 구현해야합니다. 이것은 ng-app에서 제대로 표시하는 방법 일뿐입니다.


1
나는 클라이언트 측 논리로 머리를 감싸기 위해 귀하의 가이드를 따르고 있습니다. 이거 정말 좋다!! 세션을 수동으로 파괴하는 것에 대해 놓친 부분이 있었지만 실험도해야하고 파괴해야합니다!
Sebastialonso

~~ 내가 그 줄을 정확하게 이해하는지 확실하지 않다 : authService.login() = [...]그 대괄호는 다음과 같은 것을 의미 할 것이다 $http.get(url, {uID, pwd}? ~~ 좋아, 플 런커를 들여다 보았다. 내가 XD를
말했던 것과 같았다

1
서버 측에 대한 답변을 확장 할 수 있습니까?
쿼리

25

나는 접근 방식을 좋아하고 프런트 엔드에서 인증 관련 작업을 수행하지 않고 서버 측에서 구현했습니다.

내 최신 앱에서 내 '기술'은 .. 클라이언트가 Auth를 신경 쓰지 않는다는 것입니다. 앱의 모든 항목은 먼저 로그인이 필요하므로 세션에서 기존 사용자가 감지되지 않는 한 서버는 항상 로그인 페이지를 제공합니다. session.user가 발견되면 서버는 index.html 만 보냅니다. Bam : -o

"Andrew Joslin"의 의견을 찾으십시오.

https://groups.google.com/forum/?fromgroups=#!searchin/angular/authentication/angular/POXLTi_JUgg/VwStpoWCPUQJ


3
웹 API라면? 난 내가 :( 추측 답 얻을 didnt는
레안드로 드 멜로 Fagundes

1
사용자 이름을 표시하려면 어떻게해야합니까? 또는 엔드 포인트 URL에있는 사용자 이름으로 서비스와 대화하는 경우?
perrygeo 2011 년

2
미안하지만 대답을 이해하지 못합니다. 각도에서 세션을 어떻게 처리합니까? session.user는 어디에 있습니까? 이것의 코드 예제를 만들어 주시겠습니까? 감사합니다
프랑수아 로맹에게

4
세션은 서버 측이 아니라 클라이언트 측에서 처리되며 클라이언트는 토큰을 저장하고 모든 요청의 일부로 보냅니다. 서버는 토큰의 유효성을 검사하고 요청을 처리합니다
daydreamer

4
그것을 이해하는 사람이 나머지 우리를 위해이 답변을 편집 할 수 있습니까?
Alojz Janez

14

비슷한 질문에 대답했습니다 .AngularJS 인증 + RESTful API


보호 / 공개 경로, 로그인 / 로그 아웃시 재 라우팅, 상태 확인을위한 하트 비트, 쿠키, 이벤트 등에 세션 토큰을 저장하는 UserAppAngularJS 모듈 을 작성했습니다 .

다음 중 하나를 수행 할 수 있습니다.

  1. 모듈을 수정하고 자신의 API에 연결하거나
  2. UserApp (클라우드 기반 사용자 관리 API) 과 함께 모듈 사용

https://github.com/userapp-io/userapp-angular

UserApp을 사용하는 경우 사용자 항목에 대한 서버 측 코드를 작성할 필요가 없습니다 (토큰 유효성 검사 이상). Codecademy과정을 수강 하여 사용해보십시오.

작동 방식에 대한 몇 가지 예는 다음과 같습니다.

  • 공개 할 경로와 로그인 양식 인 경로를 지정하는 방법 :

    $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
    $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
    $routeProvider.when('/home', {templateUrl: 'partials/home.html'});

    .otherwise()경로는 당신이 당신의 사용자가 로그인 후 리디렉션 할 위치로 설정해야합니다. 예:

    $routeProvider.otherwise({redirectTo: '/home'});

  • 오류 처리가 포함 된 로그인 양식 :

    <form ua-login ua-error="error-msg">
        <input name="login" placeholder="Username"><br>
        <input name="password" placeholder="Password" type="password"><br>
        <button type="submit">Log in</button>
        <p id="error-msg"></p>
    </form>
  • 오류 처리가 포함 된 가입 양식 :

    <form ua-signup ua-error="error-msg">
      <input name="first_name" placeholder="Your name"><br>
      <input name="login" ua-is-email placeholder="Email"><br>
      <input name="password" placeholder="Password" type="password"><br>
      <button type="submit">Create account</button>
      <p id="error-msg"></p>
    </form>
  • 로그 아웃 링크 :

    <a href="#" ua-logout>Log Out</a>

    (세션을 종료하고 로그인 경로로 리디렉션)

  • 사용자 속성에 액세스 :

    사용자 속성은 user서비스를 사용하여 액세스됩니다. 예 :user.current.email

    또는 템플릿에서 : <span>{{ user.email }}</span>

  • 로그인했을 때만 표시되어야하는 요소 숨기기 :

    <div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>

  • 권한에 따라 요소를 표시합니다.

    <div ua-has-permission="admin">You are an admin</div>

백엔드 서비스를 인증하려면을 사용 user.token()하여 세션 토큰을 가져 와서 AJAX 요청과 함께 보냅니다. 백엔드에서 UserApp API ( UserApp을 사용하는 경우)를 사용하여 토큰이 유효한지 확인합니다.

도움이 필요하면 알려주세요!


"모듈을 수정하고 자신의 API에 연결" 하는 방법은 무엇입니까?
Pureferret 2015 년

2

angularjs에서는 UI 부분, 서비스, 지시문 및 UI를 나타내는 angularjs의 모든 부분을 만들 수 있습니다. 작업하기에 좋은 기술입니다.

이 기술을 처음 접하고 "사용자"를 인증하려는 사람이라면 C # 웹 API의 힘으로 수행하는 것이 좋습니다. 이를 위해 사용자를 인증하는 강력한 보안 메커니즘을 구축하는 데 도움이되는 OAuth 사양을 사용할 수 있습니다. OAuth로 WebApi를 빌드 한 후에는 토큰에 대해 해당 API를 호출해야합니다.

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

토큰을 받으면 Token의 도움으로 angularjs에서 리소스를 요청하고 OAuth 사양으로 웹 API에서 안전하게 유지 된 리소스에 액세스합니다.

더 많은 도움이 필요하면 아래 기사를 살펴보십시오.

http://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/


1

모든 JSON 응답은 속성 (예 : {authenticated : false})을 포함해야하며 클라이언트는 매번 테스트해야한다고 생각합니다. false이면 Angular 컨트롤러 / 서비스가 로그인 페이지로 "리디렉션"됩니다.

그리고 사용자가 JSON을 잡아서 bool을 True로 변경하면 어떻게 될까요?

이런 종류의 일을 클라이언트 측에 의존해서는 안된다고 생각합니다. 사용자가 인증되지 않은 경우 서버는 로그인 / 오류 페이지로 리디렉션해야합니다.


2
확인 : github.com/witoldsz/angular-http-auth- 인터셉터가 서버 응답 상태 코드를 확인하고 403 ( '로그인 필요') 인 경우 이벤트를 브로드 캐스트하므로 앱 내에서이를 포착하고 로그인 상자를 표시 할 수 있습니다.
aherok 2011-06-11

10
답변을 사용하여 서로 답장하지 마십시오. 그게 댓글의 목적입니다!
Soviut

@aherok 제안, 귀하의 의견은 답변으로 승격되어야하며, 시간 내에 최고에 투표 될 것입니다. 나머지는 소음입니다.
user237419

0

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.