使用angular4和asp.net core 2 web api做个练习项目(三)

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

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

后台代码: https://github.com/solenovex/asp.net-core-2.0-web-api-boilerplate

前台代码: https://github.com/solenovex/angular-4-client-panel-app

下面将开发登陆和授权的部分, 这里要用到identity server 4.

在VS解决方案中设置多个项目同时启动:

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

CoreApi.Web作为api, 都已经配置好了.它的地址是 http://localhost:5001

Login 登陆

由于我们使用的是Identity Server 4的登录页面, 所以angular项目里面无需登录页面, 把login相关的文件删除...........

登陆需要使用到oidc-client.js所以通过npm安装:

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里面却没有.

今天比较忙, 先写到这... 估计还得写一篇....

时间: 2024-10-08 14:37:26

使用angular4和asp.net core 2 web api做个练习项目(三)的相关文章

基于ASP.NET Core 创建 Web API

使用 Visual Studio 创建项目. 文件->新建->项目,选择创建 ASP.NET Core Web 应用程序. 基于 ASP.NET Core 2.0 ,选择API,身份验证选择:不进行身份验证. 至此,就完成了一个ASP.NET Core项目的创建,项目中已经默认创建了一个ValuesController,F5运行项目,可以在浏览器调用已经存在的API. 参考资料: ASP.NET Core 中文文档 第二章 指南(2)用 Visual Studio 和 ASP.NET Core

ASP.NET Core Web Api之JWT刷新Token(三)

原文:ASP.NET Core Web Api之JWT刷新Token(三) 前言 如题,本节我们进入JWT最后一节内容,JWT本质上就是从身份认证服务器获取访问令牌,继而对于用户后续可访问受保护资源,但是关键问题是:访问令牌的生命周期到底设置成多久呢?见过一些使用JWT的童鞋会将JWT过期时间设置成很长,有的几个小时,有的一天,有的甚至一个月,这么做当然存在问题,如果被恶意获得访问令牌,那么可在整个生命周期中使用访问令牌,也就是说存在冒充用户身份,此时身份认证服务器当然也就是始终信任该冒牌访问令

ABP示例程序-使用AngularJs,ASP.NET MVC,Web API和EntityFramework创建N层的单页面Web应用

本片文章翻译自ABP在CodeProject上的一个简单示例程序,网站上的程序是用ABP之前的版本创建的,模板创建界面及工程文档有所改变,本文基于最新的模板创建.通过这个简单的示例可以对ABP有个更深入的了解,每个工程里应该写什么样的代码,代码如何组织以及ABP是如何在工程中发挥作用的. 源文档地址:https://www.codeproject.com/Articles/791740/Using-AngularJs-ASP-NET-MVC-Web-API-and-EntityFram 源码可以

Asp.Net MVC 4 Web API 中的安全认证-使用OAuth

Asp.Net MVC 4 Web API 中的安全认证-使用OAuth 各种语言实现的oauth认证: http://oauth.net/code/ 上一篇文章介绍了如何使用基本的http认证来实现asp.net web api的跨平台安全认证. 这里说明一个如何使用oauth实现的认证.oauth大家可能不陌生.那么这里需要注意的是我们使用的是.net平台一个比较好的开源oauth库. DOTNETOPENAUTH. 就像上图所示,我们需要一个ISSSUE Server来给我们一个token

[Asp.Net] MVC 和Web API 的区别

Asp.net MVC 和web api 的action 在获取从前台传入的数据是有很大不同 前台使用ajax的方式向后台发起post的请求 Content-Type:application/json 使用以下json对象 { "user": { "Username":"xxx", "Password":"xxxx" } } { "Username":"xxx", &

ASP.NET Core环境Web Audio API+SingalR+微软语音服务实现web实时语音识别

处于项目需要,我研究了一下web端的语音识别实现.目前市场上语音服务已经非常成熟了,国内的科大讯飞或是国外的微软在这块都可以提供足够优质的服务,对于我们工程应用来说只需要花钱调用接口就行了,难点在于整体web应用的开发.最开始我实现了一个web端录好音然后上传服务端进行语音识别的简单demo,但是这种结构太过简单,对浏览器的负担太重,而且响应慢,交互差:后来经过调研,发现微软的语音服务接口是支持流输入的连续识别的,因此开发重点就在于实现前后端的流式传输.参考这位国外大牛写的博文Continuou

asp.net core 系列之用户认证(1)-给项目添加 Identity

对于没有包含认证(authentication),的项目,你可以使用基架(scaffolder)把 Identity的程序集包加入到项目中,并且选择性的添加Identity的代码进行生成. 虽然基架已经生成了很多必须的代码,但是你仍然需要更新你的项目来完善这个过程. 这篇文章主要就是解释完善Identity基架进行更新的一些步骤 当Identity基架添加以后,一个ScaffoldingReadme.txt 文件就被创建了,这里面会包含一些完善Identity基架的说明.如下 Scaffoldi

Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案 (精髓)

前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件夹说起.问题大概有以下几点: 1.项目层的文件夹结构 2.解决MVC的Controller和Web API的Controller类名不能相同的问题 3.给MVC不同命名空间的Area的注册不同的路由 4.让Web API路由配置也支持命名空间参数 5.MVC及Web API添加身份验证及错误处理的过滤器

Asp.net Core WebApi 使用Swagger做帮助文档,并且自定义Swagger的UI

WebApi写好之后,在线帮助文档以及能够在线调试的工具是专业化的表现,而Swagger毫无疑问是做Docs的最佳工具,自动生成每个Controller的接口说明,自动将参数解析成json,并且能够在线调试. 那么要讲Swagger应用到Asp.net Core中需要哪些步骤,填多少坑呢? 安装Swagger到项目 { "dependencies": { "Swashbuckle": "6.0.0-beta902", ........ 或者直接通