JHipster一知半解- 4.6.4 webapp-share

2018-06-13  本文已影响55人  沉寂之舟

回文集目录:JHipster一知半解

shared.module.ts

SharedModule整合了Lib模块,Common模块两个子模块的内容,并且重新导出,作为整个的共享模块(工具模块)使用。

@NgModule({
    //引入两个子模块
    imports: [
        JhipsterSampleApplicationNg2SharedLibsModule,
        JhipsterSampleApplicationNg2SharedCommonModule
    ],
    //声明自己的组件,指令
    declarations: [
        JhiLoginModalComponent,
        HasAnyAuthorityDirective
    ],
    //声明通用的服务,主要,由于不是在主模块provider了,只有引入SharedModule的才能使用这些
    //实际上,其他所有的子模块都有引入SharedLibsModule。
    providers: [
        LoginService,
        LoginModalService,
        AccountService,
        StateStorageService,
        Principal,
        CSRFService,
        AuthServerProvider,
        UserService,
        DatePipe
    ],
    //模块的入口组件--SharedModule并不会被路由懒加载到,所有声明并没有意义
    entryComponents: [JhiLoginModalComponent],
    exports: [
        JhipsterSampleApplicationNg2SharedCommonModule,
        JhiLoginModalComponent,
        HasAnyAuthorityDirective,
        DatePipe
    ],
    //语言模式,CUSTOM_ELEMENTS_SCHEMA是angular提供的一种模式,允许在命名时使用“-”。
    /* Defines a schema that will allow:
    * - any non-Angular elements with a `-` in their name,
    * - any properties on elements with a `-` in their name which is the common rule for custom elements.
    */
    schemas: [CUSTOM_ELEMENTS_SCHEMA]

})
export class JhipsterSampleApplicationNg2SharedModule {}

shared-libs.module.ts

@NgModule({
    imports: [
        NgbModule.forRoot(),
        NgJhipsterModule.forRoot({
            // set below to true to make alerts look like toast
            alertAsToast: false,
            i18nEnabled: true,
            defaultI18nLang: 'en'
        }),
        InfiniteScrollModule,
        CookieModule.forRoot()
    ],
    exports: [
        FormsModule,
        HttpModule,
        CommonModule,
        NgbModule,
        NgJhipsterModule,
        InfiniteScrollModule
    ]
})
export class JhipsterSampleApplicationNg2SharedLibsModule {}

SharedLibsModule比较简单,引用了NgbModule,NgJhipsterModule,InfiniteScrollModule,CookieModule,并且初始化了它们,重新导出了它们。
值得主要的是,这里是初始化ng-jhipster的地方,参见
TODO:链接ng-jhipster源码1-顶层

shared-common.module.ts

定义了内部(JHipster)实现的语言帮助(显示Title),警告组件两个部分,
奇怪的是,有的组件是放Shared顶层的,有的又放到Common里面,是因为语言帮助和警告框更有通用性吧

alert目录

JhiAlertErrorComponent和JhiAlertComponent两个组件的外观(template)是一直的,但是内部逻辑有所区别。JhiAlertComponent就完全依赖alertService,使用服务进行显示提示框。
则在JhiAlertErrorComponent在自己内部保存alert数组(也依赖alertService构造),并且通过cleanHttpErrorListener注册监听httpError的错误,通过异步的方式在compont里面进行通讯错误的提示。

auth目录

account.service.ts

@Injectable()
export class AccountService  {
    //这里注入的http是Jhipster修改过的。
    constructor(private http: Http) { }
    //调用Restful接口获取用户数据,返回一个any型,比较宽松
    get(): Observable<any> {
        return this.http.get(SERVER_API_URL + 'api/account').map((res: Response) => res.json());
    }
    //调用Restful保存获取用户数据
    save(account: any): Observable<Response> {
        return this.http.post(SERVER_API_URL + 'api/account', account);
    }
}

auth-jwt.service.ts

在Shared内部使用的登录辅助类,JWT认证方式时候的通讯类。

    //传入凭证信息,进行登录认证通讯
    login(credentials): Observable<any> {
        //post内容,用户名,密码,是否记住
        const data = {
            username: credentials.username,
            password: credentials.password,
            rememberMe: credentials.rememberMe
        };
        //这里调用api/authenticate认证,
        return this.http.post(SERVER_API_URL + 'api/authenticate', data).map(authenticateSuccess.bind(this));

        function authenticateSuccess(resp) {
            //登录成功从返回报文头获取Authorization,并且使用魔数“Bearer ”分隔。
            const bearerToken = resp.headers.get('Authorization');
            if (bearerToken && bearerToken.slice(0, 7) === 'Bearer ') {
                const jwt = bearerToken.slice(7, bearerToken.length);
                this.storeAuthenticationToken(jwt, credentials.rememberMe);
                return jwt;
            }
        }
    }
    //另外一种登录方式,仅保存的jwt信息,无需特别通讯(在每次通讯的报文头都会带上jwt的token信息)
    loginWithToken(jwt, rememberMe) {
        if (jwt) {
            this.storeAuthenticationToken(jwt, rememberMe);
            return Promise.resolve(jwt);
        } else {
            return Promise.reject('auth-jwt-service Promise reject'); // Put appropriate error message here
        }
    }
    //根据rememberMe的值,决定是保存到$localStorage还是$sessionStorage
    storeAuthenticationToken(jwt, rememberMe) {
        if (rememberMe) {
            this.$localStorage.store('authenticationToken', jwt);
        } else {
            this.$sessionStorage.store('authenticationToken', jwt);
        }
    }
    //无http操作,仅清空本地存储的token即可
    logout(): Observable<any> {

        return new Observable((observer) => {
            this.$localStorage.clear('authenticationToken');
            this.$sessionStorage.clear('authenticationToken');
            observer.complete();
        });
    }

其中$localStorage和$sessionStorage是由ngx-webstorage(之前是ng2-webstorage)提供的浏览器端存储服务,顾名思义可知,API调用方法相同,存储的位置,有效期不同。

csrf.service.ts

从cookie中获取XSRF-TOKEN的值。

has-any-authority.directive.ts

通过判断权限列表,决定页面某个标签是否显示。通过注入principal进行判断。其判断有点类似ngif的指令,根据输入的值,调用viewContainerRef重新绘制页面。

P.S Jhipster的权限控制,大都是Hard code近代码的,比较简单,动态性小。

principal.service.ts

核心的服务,保存用户的认证信息,用户名,是否认证,认证状态主题(Subject),核心代码为几个用户权限的判断hasAnyAuthority(hasAnyAuthority,hasAnyAuthorityDirect,hasAuthority),以及用户状态的判断isAuthenticated。

state-storage.service.ts

constructor(
        private $sessionStorage: SessionStorageService
    ) {}

在构造器中注入$sessionStorage,用来在URL跳转中能记录状态。主要包括previousState,destinationState,previousUrl三种信息。其中previousState包含name和params两个内容。

storePreviousState(previousStateName, previousStateParams) {
        const previousState = { 'name': previousStateName, 'params': previousStateParams };
        this.$sessionStorage.store('previousState', previousState);
    }

destinationState包含目标状态destinationState,目标参数destinationStateParams,目标来源fromState三个内容

storeDestinationState(destinationState, destinationStateParams, fromState) {
        const destinationInfo = {
            'destination': {
                'name': destinationState.name,
                'data': destinationState.data,
            },
            'params': destinationStateParams,
            'from': {
                'name': fromState.name,
            }
        };
        this.$sessionStorage.store('destinationState', destinationInfo);
    }

user-route-access-service.ts

它是一个路由守卫CanActivate,用来控制能否进行url跳转,进入某个页面,核心方法为canActivate,调用checkLogin进行验证
checkLogin(authorities: string[], url: string): Promise<boolean> {
        const principal = this.principal;
        //返回一个Promise对象
        return Promise.resolve(principal.identity().then((account) => {
            //判断要求的权限列表,为空直接放行
            if (!authorities || authorities.length === 0) {
                return true;
            }
            //如果登录情况,调用principal是否具有权限
            if (account) {
              return principal.hasAnyAuthority(authorities).then(
                (response) => {
                  if (response) {
                    return true;
                  }
                  return false;
                }
              );
            }
            //登记当前url,调用stateStorageService存储当前url,并且通过loginModalService显示登录框给用户登录。
            this.stateStorageService.storeUrl(url);
            this.router.navigate(['accessdenied']).then(() => {
                // only show the login dialog, if the user hasn't logged in yet
                if (!account) {
                    this.loginModalService.open();
                }
            });
            return false;
        }));
    }
上一篇下一篇

猜你喜欢

热点阅读