栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

malagu认证与授权之@malagu/security

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

malagu认证与授权之@malagu/security

导言
  • 本文已参与「开源摘星计划」,欢迎正在阅读的你加入。活动链接:https://github.com/weopenprojects/WeOpen-Star
  • malagu的认证与授权参考spring-security思想,详细介绍请移步官方文档。malagu除了基本的security外提供了ODIC 的认证和 OAuth2.0 的授权能力,本文主要介绍@malagu/security组件的基本应用实践。
认证与授权组件 @malagu/security的简单应用
  • 1.添加组件
    在项目中引用@malagu/security组件
yarn add @malagu/security # 或者 npm i @malagu/security
  • 2.重写loginUrl和logoutUrl
    定义登录和注销接口和请求方式
malagu:
  security:
    loginUrl: /api/login
    loginMethod: POST    
    logoutUrl: /api/logout
  • 3.重写UserService实现自定义登录
    注册用户时密码需要使用PasswordEncoder生成;
    我们只需将用户和密码在load()中赋值给security组件User即可,校验比对逻辑交由@malagu/security组件完成。
import { Component, Autowired } from '@malagu/core';
import { UserService, UsernameNotFoundError, AccountStatusError, PasswordEncoder } from '@malagu/security/lib/node';
import { User, ElPolicy, PolicyType, AuthorizeType } from '@malagu/security';
import { OrmContext, Transactional } from "@malagu/typeorm/lib/node";
import { UserEntity } from '@microservice/datasource';


@Component({ id: UserService, rebind: true })
export class UserServiceImpl implements UserService {

    @Autowired(PasswordEncoder)
    protected readonly passwordEncoder: PasswordEncoder;

    @Transactional({ readOnly: true })
    async load(username:string): Promise{
        const repo = OrmContext.getRepository(UserEntity);

        let user = await repo.findOne({ userName: username })       
        if (!user) {
          user = await repo.findOne({ mobile: username })
        }
    
        if (!user) {
          throw new UsernameNotFoundError();
        }
        if(user.state == false){
          throw new AccountStatusError();
        }
        
        return  {
            type: "",
            username: user.userName,
            password: user.password,
            policies: [ {
                type: PolicyType.el,
                authorizeType: AuthorizeType.Pre,
                el: 'true'
              } ],
            accountNonExpired: true,
            accountNonLocked: true,
            credentialsNonExpired: true,
            enabled: true
        }
    }

}
  • 4.重写认证失败处理器AuthenticationErrorHandler
import { Component, Autowired } from '@malagu/core';
import { HttpStatus } from '@malagu/web';
import { ErrorHandler, Context, RedirectStrategy } from '@malagu/web/lib/node';
import { AuthenticationErrorHandler, 
    AUTHENTICATION_ERROR_HANDLER_PRIORITY, 
    AuthenticationError  } from '@malagu/security/lib/node'

@Component({ id: AuthenticationErrorHandler, rebind: true })
export class AuthenticationErrorHandlerImpl implements ErrorHandler{
    readonly priority: number = AUTHENTICATION_ERROR_HANDLER_PRIORITY;

    @Autowired(RedirectStrategy)
    protected readonly redirectStrategy: RedirectStrategy;


    canHandle(ctx: Context, err: Error): Promise {
        return Promise.resolve(err instanceof AuthenticationError);
    }

    async handle(ctx: Context, err: AuthenticationError): Promise {
        let message = "";
        switch (err.name) {
            case "UsernameNotFoundError":
                ctx.response.statusCode = HttpStatus.FORBIDDEN;    
                message = "用户不存在";           
                break; 
            case "BadCredentialsError":
                ctx.response.statusCode = HttpStatus.FORBIDDEN;    
                message = "用户密码错误";           
                break;  
            case "AccountStatusError":
                ctx.response.statusCode = HttpStatus.FORBIDDEN;    
                message = "用户被冻结";           
                break;
            case "AuthenticationError":
                ctx.response.statusCode = HttpStatus.UNAUTHORIZED;    
                message = "用户没有访问权限,需要进行身份认证";           
                break;            
            default:
                ctx.response.statusCode = HttpStatus.UNAUTHORIZED;
                message = err.message;
                break;
        }        
        ctx.response.end(message);
    }

}

  • 5.重写认证成功处理器AuthenticationSuccessHandler
    非必需,不重写将跳转到首页
import { Component } from '@malagu/core';
import { HttpStatus } from '@malagu/web';
import { AuthenticationSuccessHandler, Authentication } from '@malagu/security/lib/node'
import { Context } from '@malagu/web/lib/node'

@Component({ id: AuthenticationSuccessHandler, rebind: true })
export class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {

    async onAuthenticationSuccess(authentication: Authentication): Promise {
        Context.getResponse().statusCode = HttpStatus.OK;
        Context.getResponse().body = JSON.stringify({ username: authentication.name });
    }

}
  • 6.重新登出处理器LogoutSuccessHandler
    非必需,不重写将跳转到登录页
import { LogoutSuccessHandler, LOGOUT_SUCCESS_HANDLER_PRIORITY } from '@malagu/security/lib/node';
import { Component } from '@malagu/core';
import { HttpStatus } from '@malagu/web';
import { Context } from '@malagu/web/lib/node';

@Component({id: LogoutSuccessHandler, rebind: true })
export class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {

    readonly priority = LOGOUT_SUCCESS_HANDLER_PRIORITY;

    async onLogoutSuccess(): Promise {
        Context.getResponse().statusCode = HttpStatus.OK;
        Context.getResponse().body = "登出成功";
    }
}

  • 7.@Authenticated的使用
    可以在controller类上使用,这样该类下的所有开放接口都需要鉴权
@Controller("user")
@Authenticated()
export class UserController {

    @Autowired(UserInfoService)
    protected userInfoService: UserInfoService;
    ... ...
}

也可以在指定的接口上使用

    @Get("/:userId")
    @Json()
    @Authenticated()
    async getUserInfo(@Param("userId") userId: number){
        const result = await this.userInfoService.getUserInfo(userId);     
        return result  

    }
  • 8.除了@Authenticated,malagu还提供了用于权限控制的装饰器@PreAuthorize以及匿名@Anonymous
结语

至此,@malagu/security的核心代码就已经完成。在module.ts文件引用,运行项目我们就可以进行的调试了。由于登录逻辑都交由组件处理了,malagu的认证授权还是比较简单的。

思考
  • @malagu/security的原理是怎样的?
  • UserService中返回体User各属性的含义?
  • 登录有效期怎么设置?
  • 可以使用@malagu/security实现单点登录吗?

*** 本文为学习分享文章,如有错误欢迎指正!思考内容欢迎各位大佬答疑解惑。***

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1039715.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号