Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之显示登录视图

  1. 尝试新的开发组合:Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS
  2. Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之配置IdentityServer
  3. Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之数据迁移
  4. Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之添加实体
  5. Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之显示登录视图

在上一篇文章,完成了实体的定义,接下来要做的是定义应用服务,以便提供api接口。不过,为了更好的结合客户端,笔者决定暂时把这个工作缓一下,和客户端的改造一同进行。

新建一个名为SimpleCmsWithAbp-Client的文件夹,把SimpleCMS的Ext JS脚本复制到文件夹中。然后用Visual Studio Code打开该文件夹。使用Visual Studio Code是因为在这里不需要编写C#代码,使用vscode比使用Visual Studio方便很多。

打开文件夹后,先为vscode安装一个名为IIS Express的扩展(warren-buckley.iis-express)用来启动IIS Express。扩展安装完成后,就可在打开的文件中单击鼠标右键,在菜单中选择命令面板,就可在如下图所示的输入框中执行以下命令来启动、重新启动或停止IIS Express了:

  • IIS Express: Start Website - 启动IIS Express
  • IIS Express: Stop Website - 停止IIS Express
  • IIS Express: Restart Website - 重新启动IIS Express

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之显示登录视图_第1张图片

由于ABP框架模版默认是使用4200端口来作为跨域访问的客户端网站端口的,因而,我们需要将当前文件夹的访问端口设置为4200。在当前文件夹下新建一个名为.vscode的文件夹,然后在文件夹下创建一个名为iisexpress.json的文件,并在里面添加以下代码:

{
    "port":4200
}

好了,现在可以启动IIS Express来访问网站了,不过执行肯定是错误的。我们先打开app.json文件,将里面的首页文件(indexHtmlPath)设置回index.html。然后打开index.html文件,在调用bootstrap.js脚本的SCRIPT标记前添加以下代码:

    <script>
        var ROOTPATH = 'http://localhost:21021';
        var LOCALPATH = 'http://localhost:4200';
    script>

以上代码用于指定远程访问地址和本地地址。

接下来打开app\util\Url.js,将getResource方法修改为以下代码:

    getResource: function (res) {
        var me = this;
        return LOCALPATH + '/' + me.resources[res];
    }

代码完成后按CTRL+打开终端窗口执行一次sencha app build`,重建生成一次项目。现在在浏览器访问应用,会正常显示界面了,不过会提示访问错误。问题不大,接下来就是要修正这些问题。

WebApi是通过令牌认证(Token Auth)来访问的,需要在Ajax的头部添加Authorization来发送认证令牌。在修改Ajax的头部前,需要先考虑这令牌如何保存的问题。根据《Where to Store your JWTs – Cookies vs HTML5 Web Storage》一文,建议的方法是将令牌保存在Cookies中,但这又带来一个CORS的安全问题,需要为Ajax开启cors保护。

在研究了ABP框架模版自带的angular版本客户端的启动过程(AppPreBootstrap.ts),会发现在提交请求时,会在Ajax的头部添加Authorization.AspNetCore.CultureAbp.TenantId这三个头。为了便于在Ajax请求添加这三个头,我们可在app\util文件夹下,新建一个名为Headers.js的脚本文件,然后添加以下代码:

Ext.define('SimpleCMS.util.Headers',{
    alternateClassName: 'HEADERS',
    singleton: true,

    requires:[
        'Ext.util.Cookies'
    ],

    authTokenCookieName : 'Abp.AuthToken',
    authTokenHeaderName : 'Authorization',
    tenantIdCookieName : 'Abp.TenantId',
    tenantIdHeaderName: 'Abp.TenantId',
    cultureTCookieName: 'Abp.Localization.CultureName',
    cultureHeaderName: '.AspNetCore.Culture',

    getAuthToken: function(){
        return Ext.util.Cookies.get(this.authTokenCookieName);
    },

    getTenantId: function(){
        return Ext.util.Cookies.get(this.tenantIdCookieName);
    },


    getCulture: function(){
        return Ext.util.Cookies.get(this.cultureTCookieName);
    },

    setCookies: function(name, value , expires , path , domain , secure ){
        Ext.util.Cookies.set(name, value , expires , path , domain , secure);
    },


    getHeaders: function(){
        var me = this;
        return {
            'Authorization' : 'Bearer ' +  me.getAuthToken(),
            'Abp.TenantId' : me.getTenantId(),
            '.AspNetCore.Culture' : me.getCulture()
        }
    }


});

方法getHeaders用户返回组合好的头部,还有3个get方法用于从Cookies中返回令牌、当前用户的默认语言和组合编号,setCookies方法则用于存储Cookies。添加Header类后,在app.js中添加对它的引用。

为了方便的将请求头自动写入Ajax请求的头部,而不需要每次写请求时才加入,最好的方式是重写Ext.Ajax类或在发送请求前统一处理。由于Ext.Ajax是单例模式的类,不便于重写,因而只有在发送请求前统一处理了。经过查看API,发现Ext.Ajax有beforerequest事件,正是所需的。接下来要考虑的是在哪里执行了。经过测试,发现在Application.jslaunch方法是不行,因为这时候主视图已经初始化并开始执行流程了。通过查阅Ext.app.Application的API,发现还有一个init方法,它会在主视图初始化之前执行,正是所需的。在init方法中添加以下代码:

    init: function(){
        Ext.util.Format.defaultValue = function (value, defaultValue) {
            return Ext.isEmpty(value) ? defaultValue : value;
        }
        Ext.Ajax.on('beforerequest', this.onAjaxBeforeRequest, this);
        Ext.Ajax.cors = true;        
    },

在代码中,通过on方法将beforerequest事件绑定到了onAjaxBeforeRequest方法。将cors设置为true是打开Ajax的CORS防御机制。

方法onAjaxBeforeRequest的代码如下:

    onAjaxBeforeRequest: function(conn , options , eOpts ){
        if(!options.headers) options.headers = {}
        Ext.apply( options.headers, HEADERS.getHeaders());
        options.jsonData = true;
    }

代码先判断Ajax的选项是否已包含headers的配置,如果没有,则将headers设置为一个对象,然后调用getHeaders方法将返回的头部信息通过apply方法复制到headers中。将jsonData设置为true是为了将提交的contentType设置为application/json,而不是默认的text/plain

由于使用的是令牌认证,因而,只要验证一下Cookies中是否存在令牌,就可知道用户是否已经登录,如果没有,则显示登录页,如果有,则去获取用户信息。打开app\view\main\MainController.js文件,在onMainViewRender方法中,将代码修改为以下代码:

    onMainViewRender: function () {
        var me = this,
            token = HEADERS.getAuthToken();
        if (Ext.isEmpty(token)) {
            me.setCurrentView("login");
            return;
        }
    },

好了,现在可以显示登录视图了。总的感觉来说,这比原来的方式简单不少。

你可能感兴趣的:(ASP/ASP.NET,ExTJS)