使用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.

第一部分: 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里面却没有.

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

 

下面是我的关于ASP.NET Core Web API相关技术的公众号--草根专栏:

目录
相关文章
|
10月前
|
安全 Java API
Java Web 在线商城项目最新技术实操指南帮助开发者高效完成商城项目开发
本项目基于Spring Boot 3.2与Vue 3构建现代化在线商城,涵盖技术选型、核心功能实现、安全控制与容器化部署,助开发者掌握最新Java Web全栈开发实践。
835 1
|
11月前
|
JavaScript Java 微服务
现代化 Java Web 在线商城项目技术方案与实战开发流程及核心功能实现详解
本项目基于Spring Boot 3与Vue 3构建现代化在线商城系统,采用微服务架构,整合Spring Cloud、Redis、MySQL等技术,涵盖用户认证、商品管理、购物车功能,并支持Docker容器化部署与Kubernetes编排。提供完整CI/CD流程,助力高效开发与扩展。
1151 64
|
开发框架 前端开发 JavaScript
ASP.NET Web Pages - 教程
ASP.NET Web Pages 是一种用于创建动态网页的开发模式,采用HTML、CSS、JavaScript 和服务器脚本。本教程聚焦于Web Pages,介绍如何使用Razor语法结合服务器端代码与前端技术,以及利用WebMatrix工具进行开发。适合初学者入门ASP.NET。
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
自然语言处理 算法 API
阿里云增值税发票识别NET Rest API调用示例
本文介绍了使用NET代码调用阿里云增值税发票识别API的实现方式。通过示例代码,详细展示了如何构造请求、设置签名以及发送HTTP请求的具体步骤。代码中涵盖了请求参数的处理、签名生成逻辑(如HMAC-SHA256算法)以及调用API后的结果处理。此外,还提供了运行结果的截图和参考文档链接,帮助开发者更好地理解和应用该接口。
1439 4
|
安全 JavaScript Java
java Web 项目完整案例实操指南包含从搭建到部署的详细步骤及热门长尾关键词解析的实操指南
本项目为一个完整的JavaWeb应用案例,采用Spring Boot 3、Vue 3、MySQL、Redis等最新技术栈,涵盖前后端分离架构设计、RESTful API开发、JWT安全认证、Docker容器化部署等内容,适合掌握企业级Web项目全流程开发与部署。
1048 0
|
人工智能 安全 程序员
用 Colab 和 ngrok 免费部署你的 Web UI 项目,随时随地访问!
用 Colab 和 ngrok 免费部署你的 Web UI 项目,随时随地访问!
1655 12
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
1086 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
自然语言处理 API 开发者
DeepSeek-Free-API:DeepSeekV3免费的api接口,需要使用api方式的同学可以参考一下这个项目,可以收藏起来试一下
嗨,大家好,我是小华同学。今天为大家介绍一个开源项目——DeepSeek V3 Free 服务。该项目基于 DeepSeek-V3 R1 大模型,提供免费、高性能的 API,支持高速流式输出、多轮对话、联网搜索和深度思考等功能。适用于智能客服、内容创作、教育辅助等场景。部署方式灵活,支持 Docker、Docker-compose、Render、Vercel 和原生部署。欢迎关注我们,获取更多优质开源项目和高效工作学习方法。
3385 15
|
人工智能 Java API
ai-api-union项目,适配各AI厂商api
本项目旨在实现兼容各大模型厂商API的流式对话和同步对话接口,现已支持智谱、豆包、通义、通义版DeepSeek。项目地址:[https://gitee.com/alpbeta/ai-api-union](https://gitee.com/alpbeta/ai-api-union)。通过`ChatController`类暴露两个接口,入参为`ChatRequest`,包含会话ID、大模型标识符和聊天消息列表。流式对话返回`Flux&lt;String&gt;`,同步调用返回`String`