asp.net core系列 58 IS4 基于浏览器的JavaScript客户端应用程序

Posted 花阴偷移

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了asp.net core系列 58 IS4 基于浏览器的JavaScript客户端应用程序相关的知识,希望对你有一定的参考价值。

一. 概述

  本篇探讨使用"基于浏览器的javascript客户端应用程序"。与上篇实现功能一样,只不过这篇使用JavaScript作为客户端程序,而非core mvc的后台代码HttpClient实现。 功能一样:用户首先要登录IdentityServer站点,再使用IdentityServer发出的访问令牌调用We​​b API,可以注销IdentityServer站点下登录的用户,清除cookie中的令牌信息。所有这些都将来自浏览器中运行的JavaScript。

  此示例还是三个项目:

    IdentityServer令牌服务项目 http://localhost:5000

    API资源项目 http://localhost:5001

    JavaScript客户端项目 http://localhost:5003

  开源Github

 

二. IdentityServer项目

  1.1 定义客户端配置

    Config.cs中,定义客户端,使用code 授权码模式,即先登录获取code,再获取token。项目其它处代码不变。

       public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                // JavaScript Client
                new Client
                {
                    ClientId = "js",
                    ClientName = "JavaScript Client",
                    //授权码模式
                    AllowedGrantTypes = GrantTypes.Code,
                    //基于授权代码的令牌是否需要验证密钥,默认为false
                    RequirePkce = true,
                    //令牌端点请求令牌时不需要客户端密钥
                    RequireClientSecret = false,

                    RedirectUris =           { "http://localhost:5003/callback.html" },
                    PostLogoutRedirectUris = { "http://localhost:5003/index.html" },

                    //指定跨域请求,让IdentityServer接受这个指定网站的认证请求。
                    AllowedCorsOrigins =     { "http://localhost:5003" },

                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1"
                    }
                }
            };
        }

    

三. API项目

  在Web API项目中配置 跨域资源共享CORS。这将允许从http:// localhost:5003 (javascript站点) 到http:// localhost:5001 (API站点) 进行Ajax调用(跨域)。项目其它处代码不变。

       public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvcCore()
                .AddAuthorization()
                .AddJsonFormatters();

            services.AddAuthentication("Bearer")
                .AddJwtBearer("Bearer", options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;

                    options.Audience = "api1";
                });

            //添加Cors服务
            services.AddCors(options =>
            {
                // this defines a CORS policy called "default"
                options.AddPolicy("default", policy =>
                {
                    policy.WithOrigins("http://localhost:5003")
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
            });
        }
        public void Configure(IApplicationBuilder app)
        {
            //添加管道
            app.UseCors("default");
            app.UseAuthentication();
            app.UseMvc();
        }

  

四. JavaScript客户端项目

    在项目中,所有代码都在wwwroot下,没有涉及到服务端代码,可以完全不用core程序来调用。目录如下所示:

    其中添加了两个html 页(index.html, callback.html),一个app.js文件,这些属于自定义文件。oidc-client.js是核心库。

 

  4.1 index页面

    用于调用登录、注销、和api。引用了oidc-client.js和app.js 

<body>
    <button id="login">Login</button>
    <button id="api">Call API</button>
    <button id="logout">Logout</button>

    <pre id="results"></pre>

    <script src="oidc-client.js"></script>
    <script src="app.js"></script>
</body>

   

   4.2 app.js

    是应用程序的主要代码,包括:登录、Api请求,注销。配置与服务端代码差不多,如下所示:

/// <reference path="oidc-client.js" />

//消息填充
function log() {
    document.getElementById(\'results\').innerText = \'\';

    Array.prototype.forEach.call(arguments, function (msg) {
        if (msg instanceof Error) {
            msg = "Error: " + msg.message;
        }
        else if (typeof msg !== \'string\') {
            msg = JSON.stringify(msg, null, 2);
        }
        document.getElementById(\'results\').innerHTML += msg + \'\\r\\n\';
    });
}

document.getElementById("login").addEventListener("click", login, false);
document.getElementById("api").addEventListener("click", api, false);
document.getElementById("logout").addEventListener("click", logout, false);

var config = {
    authority: "http://localhost:5000",
    client_id: "js",
    redirect_uri: "http://localhost:5003/callback.html",
    response_type: "code",
    scope:"openid profile api1",
    post_logout_redirect_uri : "http://localhost:5003/index.html",
};
//UserManager类
var mgr = new Oidc.UserManager(config);

//用户是否登录到JavaScript应用程序
mgr.getUser().then(function (user) {
    if (user) {
        log("User logged in", user.profile);
    }
    else {
        log("User not logged in");
    }
});

//登录
function login() {
    mgr.signinRedirect();
}

//跨域请求api
function api() {
    mgr.getUser().then(function (user) {
        var url = "http://localhost:5001/identity";

        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = function () {
            log(xhr.status, JSON.parse(xhr.responseText));
        }
        xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
        xhr.send();
    });
}

//注销
function logout() {
    mgr.signoutRedirect();
}

   4.3 callback.html

    用于完成与IdentityServer的OpenID Connect协议登录握手。对应app.js中config对象下的redirect_uri: "http://localhost:5003/callback.html"。登录完成后,我们可以将用户重定向回主index.html页面。添加此代码以完成登录过程

<body>
    <script src="oidc-client.js"></script>
    <script>
        new Oidc.UserManager({ response_mode: "query" }).signinRedirectCallback().then(function () {
            window.location = "index.html";
        }).catch(function (e) {
            console.error(e);
        });
    </script>
</body>

 

五 测试

  (1) 启动IdentityServer程序http://localhost:5000

  (2) 启动API程序http://localhost:5001。这二个程序属于服务端

  (3) 启动javascriptClient程序 http://localhost:5003

  (4) 用户点击login,开始握手授权,重定向到IdentityServer站点的登录页

  (5) 输入用户的用户名和密码,登录成功。跳转到IdentityServer站点consent同意页面

  (6) 点击 yes allow后,跳回到客户端站点http://localhost:5003/index.html,完成了交互式身份认证。

  (7) 调用点击Call API按钮,获取访问令牌,请求受保护的api资源。调用CallAPI 时,是访问的api站点http://localhost:5001/identity。

 

参考文献

  添加JavaScript客户端

 

以上是关于asp.net core系列 58 IS4 基于浏览器的JavaScript客户端应用程序的主要内容,如果未能解决你的问题,请参考以下文章

基于ASP.NET Core 6.0的整洁架构,asp.net core 6.0 功能

Asp.net core 简单介绍

理解ASP.NET Core

基于ASP.NET Core 6.0的整洁架构

Asp.Net Core 2.0 项目实战NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架

asp.net core系列 63 领域模型架构 eShopOnWeb项目分析 上