使用angular4和asp.net core 2 web api作個練習項目(三)

第一部分: http://www.cnblogs.com/cgzl/p/7755801.htmlcss

第二部分: http://www.cnblogs.com/cgzl/p/7763397.htmlhtml

後臺代碼: https://github.com/solenovex/asp.net-core-2.0-web-api-boilerplategit

前臺代碼: https://github.com/solenovex/angular-4-client-panel-appgithub

 

下面將開發登錄和受權的部分, 這裏要用到identity server 4.web

在VS解決方案中設置多個項目同時啓動:npm

AspNetIdentityAuthorizationServer就是authorization server. 它的地址是 http://localhost:5000api

CoreApi.Web做爲api, 都已經配置好了.它的地址是 http://localhost:5001瀏覽器

Login 登錄

因爲咱們使用的是Identity Server 4的登陸頁面, 因此angular項目裏面無需登陸頁面, 把login相關的文件刪除...........服務器

登錄須要使用到oidc-client.js因此經過npm安裝:session

npm install --save oidc-client

Auth Service

須要登錄服務 auth.service:

ng g s services/auth

打開auth.services.ts:

import { Injectable, OnInit, EventEmitter } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { User, UserManager, Log } from 'oidc-client';
import 'rxjs/add/observable/fromPromise';

const config: any = {
  authority: 'http://localhost:5000',
  client_id: 'corejs',
  redirect_uri: 'http://localhost:4200/login-callback',
  response_type: 'id_token token',
  scope: 'openid profile coreapi',
  post_logout_redirect_uri: 'http://localhost:4200/index.html',
};
Log.logger = console;
Log.level = Log.DEBUG;

@Injectable()
export class AuthService implements OnInit {

  private manager: UserManager = new UserManager(config);
  public loginStatusChanged: EventEmitter<User>;

  constructor() {
    this.loginStatusChanged = new EventEmitter();
  }

  ngOnInit() {

  }

  login() {
    this.manager.signinRedirect();
  }

  loginCallBack() {
    return Observable.create(observer => {
      Observable.fromPromise(this.manager.signinRedirectCallback())
        .subscribe(() => {
          this.tryGetUser().subscribe((user: User) => {
            this.loginStatusChanged.emit(user);
            observer.next(user);
            observer.complete();
          }, e => {
            observer.error(e);
          });
        });
    });
  }

  checkUser() {
    this.tryGetUser().subscribe((user: User) => {
      this.loginStatusChanged.emit(user);
    }, e => {
      this.loginStatusChanged.emit(null);
    });
  }

  private tryGetUser() {
    return Observable.fromPromise(this.manager.getUser());
  }

  logout() {
    this.manager.signoutRedirect();
  }
}

config是針對identity server 4服務器的配置, authorization server的地址是 http://localhost:5000, 登錄成功後跳轉後來的地址是: http://localhost:4200/login-callback

其中的UserManager就是oidc-client裏面的東西, 它負責處理登陸登出和獲取當前登陸用戶等操做.

這裏login()方法被調用後會直接跳轉到 authorization server的登陸頁面.

登陸成功後會跳轉到一個callback頁面, 裏面須要調用一個callback方法, 這就是loginCallback()方法.

loginStatusChanged是一個EventEmitter, 任何訂閱了這個事件的component, 都會在登陸用戶變化時(登陸/退出)觸發component裏面自定義的事件.

logout()是退出, 調用方法後也會跳轉到authorization server的頁面.

最後別忘了在app.module裏面註冊:

  providers: [
    ClientService,
 AuthService
  ],

登錄成功後跳轉回掉頁面 

創建一個跳轉回掉的component和路由:

ng g c components/loginCallback

修改app.module的路由:

const appRoutes: Routes = [
  { path: '', component: DashboardComponent },
  { path: 'login-callback', component: LoginCallbackComponent },
  { path: 'register', component: RegisterComponent },
  { path: 'add-client', component: AddClientComponent },
  { path: 'client/:id', component: ClientDetailsComponent },
  { path: 'edit-client/:id', component: EditClientComponent }
];

打開login-callback.component.ts:

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '@angular/router';
import { User } from 'oidc-client';

@Component({
  selector: 'app-login-callback',
  templateUrl: './login-callback.component.html',
  styleUrls: ['./login-callback.component.css']
})
export class LoginCallbackComponent implements OnInit {

  constructor(
    private authService: AuthService,
    private router: Router
  ) { }

  ngOnInit() {
    this.authService.loginCallBack().subscribe(
      (user: User) => {
        console.log('login callback user:', user);
        if (user) {
          this.router.navigate(['/']); } } );
  }

}

這裏主要是調用oidc的回掉函數. 而後跳轉到主頁.

html:

<p>
  登陸成功!
</p>

這個html, 基本是看不見的.

修改Navbar

navbar.component.html:

<nav class="navbar navbar-expand-md navbar-light bg-light">
  <div class="container">
    <a class="navbar-brand" href="#">Client Panel</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault"
      aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarsExampleDefault">
      <ul class="navbar-nav mr-auto">
        <li *ngIf="isLoggedIn" class="nav-item">
          <a class="nav-link" href="#" routerLink="/">Dashboard </a>
        </li>
      </ul>
      <ul class="navbar-nav ml-auto">
        <li *ngIf="!isLoggedIn" class="nav-item">
          <a class="nav-link" href="#" routerLink="/register">Register </a>
        </li>
        <li *ngIf="!isLoggedIn" class="nav-item">
          <a class="nav-link" href="#" (click)="login()">Login </a>
        </li>
        <li *ngIf="isLoggedIn" class="nav-item">
          <a class="nav-link" href="#" (click)="logout()">Logout </a>
        </li>
      </ul>
    </div>
  </div>
</nav>
<br>

主要是檢查是否有用戶登錄了, 有的話不顯示註冊和登錄連接, 而且顯示退出連接按鈕. 沒有的話, 則顯示註冊和登陸.

navbar.component.ts:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import 'rxjs/add/operator/map';
import { User } from 'oidc-client';
import { FlashMessagesService } from 'angular2-flash-messages';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {

  public isLoggedIn: boolean;
  public loggedInUser: User;

  constructor(
    private authService: AuthService,
    private router: Router,
    private flashMessagesService: FlashMessagesService
  ) { }

  ngOnInit() {
    this.authService.loginStatusChanged.subscribe((user: User) => {
      this.loggedInUser = user;
      this.isLoggedIn = !!user;
      if (user) {
        this.flashMessagesService.show('登錄成功', { cssClass: 'alert alert-success', timeout: 4000 });
      }
    });
    this.authService.checkUser();
  }

  login() {
    this.authService.login();
  }

  logout() {
    this.authService.logout();
  }

}

在ngOnInit裏面訂閱authservice的那個登陸狀態變化的事件. 以便切換導航欄的按鈕顯示狀況.

angular的部分先到這, 而後要

修改一個identity server的配置:

在VS2017打開AspNetIdentityAuthorizationServer這個項目的Config.cs文件, 看GetClients()那部分, 裏面有一個Client是js client, 咱們就用這個....

// JavaScript Client
                new Client
                {
                    ClientId = CoreApiSettings.Client.ClientId,
                    ClientName = CoreApiSettings.Client.ClientName,
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,

                    RedirectUris =           { CoreApiSettings.Client.RedirectUris },
                    PostLogoutRedirectUris = { CoreApiSettings.Client.PostLogoutRedirectUris },
                    AllowedCorsOrigins =     { CoreApiSettings.Client.AllowedCorsOrigins },

                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        CoreApiSettings.CoreApiResource.Name
                    }
                }

打開CoreApiSettings, 它在SharedSettings這個項目裏面:

namespace SharedSettings.Settings
{
    public class CoreApiSettings
    {
        #region CoreApi

        public static string AuthorizationServerBase = "http://localhost:5000";
        public static string CorsPolicyName = "default";
        public static string CorsOrigin = "http://localhost:4200";
        public static (string Name, string DisplayName) CoreApiResource = ("coreapi", "Core APIs");
        public static (string ClientId, string ClientName, string RedirectUris, string PostLogoutRedirectUris, string AllowedCorsOrigins) Client =
            ("corejs", "Core Javascript Client", "http://localhost:4200/login-callback", "http://localhost:4200/index.html", "http://localhost:4200");

        #endregion
    }
}

把相應的地址改爲和angular auth.service裏面config同樣的地址才能工做.

這裏面使用了C# 7的命名Tuple, 很是好用.

差很少能夠了, 運行VS. 同時運行angular項目:

1. 首次瀏覽:

2. 點擊登錄:

點擊登錄就跳轉到authorization server的登陸頁面了, 你在這裏須要註冊一個用戶.....

而後輸入用戶名密碼登錄.

3.贊成受權

點擊yes 贊成受權.

4.跳轉回angular頁面:

首先跳轉回的是angular的login-callback路由, 而後瞬間回到了主頁:

5. 刷新, 仍是能夠取獲得登陸的用戶.

可是若是再打開一個瀏覽器實例就沒法取獲得登錄用戶了, oidc應該是把登錄信息存到了session storage裏面.

打開瀏覽器F12--Application:

能夠看到在session storage裏面確實有東西, 而 localstorage裏面卻沒有.

今天比較忙, 先寫到這... 估計還得寫一篇....

相關文章
相關標籤/搜索