JavaScript客户端(SPA)接入IdentityServer4

这是一个简单示例,用于演示运行在浏览器上的JavaScript客户端(也可称之为SPA)如何接入IdentityServer4。
用户首先登入IdentityServer,并获得IdentityServer颁发的access_token,然后在调用API的时候携带该 access_token,最后在退出IdentityServer登录。

创建一个简单JavaScript客户端应用

其实也就是先建立一个空项目,比如空的ASP.NET Core项目,或是 Node.js项目也行,这里是首先创建了一个空的ASP.NET Core项目

dotnet new web -n JavaScriptClient

修改托管项目的默认端口号

注意修改Properties/launchSettings.json 中的绑定地址,修改之前的 http://localhost:5003/为 http://0.0.0.0:5003, 也是之前在Docker容器运行出现绑定异常无法处理,才如此处理。

{ 
  "profiles": {
    "JavaScriptClient": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "http://0.0.0.0:5003",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

添加静态文件中间件

由于该项目主要是用于搭建一个跑在浏览器中的客户端应用,asp.net core 的主要作用就是托管静态资源,比如 HTML 和JS,静态文件中间件 也就是处理这个事情的。

在startup.cs 中注册中间件。

public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

静态文件中间件默认托管~/wwwroot目录下的静态文件,这个文件夹用来保存 HTML和JavaScript,如果没有该目录创建这个目录。

引用oidc-client

oidc-client是一个用于处理OpenID Connect (OIDC) 和 OAuth2 协议的软件开发包。可以通过npm、bower或是直接下载安装。

  • 采用 npm 安装 oidc-client

npm i oidc-client
copy node_modules\oidc-client\dist* wwwroot

这个命令也就是下载最新的oidc-client引用集,然后拷贝 javascript文件到~/wwwroot目录下。

添加你的HTML和JavaScript文件

这里会有两个HTML文件和一个项目级的JavaScript脚本文件(另外还有oidc-client.js引用库),~/wwwroot目录中添加 index.html,callback.html还有就是app.js。

index.html

这是个简单的用户首页,包含三个按钮:登录,退出和调用API。
该文件引用了两个JavaScript脚本文件。包含一个PRE标签用于输出信息。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<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>
</html>

app.js

这个文件包含了应用的所有业务逻辑处理。首先是一个通用的信息输出方法Log, 调用该方法将信息输出到 PRE标签中。

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';
    });
}

在app.js中添加三个按钮的注册文件。

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

下面就是采用oidc-client引用库中的UserManager来处理OpenID Connect协议,填写配置,初始化UserManager

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",
};
var mgr = new Oidc.UserManager(config);

接下来UserManager 提供了一个getUser的方法验证当前是否登录。返回的User 对象包含一个profile 属性,包含了所有的用户声明。

mgr.getUser().then(function (user) {
    if (user) {
        log("User logged in", user.profile);
    }
    else {
        log("User not logged in");
    }
});

接下来实现了 login、api、logout 三个方法。
UserManager 提供了signinRedirect 方法用于跳转到登录界面,signoutRedirect 退出登录。上面代码中获得的User 对象包含一个access_token ,可以用于访问API时携带。

function login() {
    mgr.signinRedirect();
}

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();
}

callback.html

这是页面是用来登录成功后跳转地址 redirect_uri ,通过这个页面完成了OpenID Connect协议的登录握手。一旦登录完成再次跳转回 index.html 页面。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<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>
</html>

代码:https://github.com/daijinming/refine-javascriptclient
演示地址:http://114.116.96.150:5003

参考:
IdentityServer4官方文档 Adding a JavaScript client

猜你喜欢

转载自blog.csdn.net/weixin_33767813/article/details/86938612