# luci-fast-security **Repository Path**: luci-fast/luci-fast-security ## Basic Information - **Project Name**: luci-fast-security - **Description**: 快速使用springboot security - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2019-05-14 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # fast-security-starter 1.0 #### 目标 基于jwt认证机制,角色匹配url规则,实现认证,鉴权的快速集成 #### 介绍 对于认证,鉴权,shiro与spring-security较为成熟,但是学习成本较高。 所以想做一个可以快速集成spring-security的拓展包,理想化是拿来即用, 因个人功底有限,现只能做到基本的快速使用,对于单服务项目,基于springboot,可以快速集成. 基本流程为:用户登陆,获取一个token,在token生命周期内,访问业务接口, 则需要在header头带上此token #### 集成指南 1.mvn package 打成jar包导入到自己的项目,或者install到自己的私服仓库 优化一段时间后,会考虑推送到maven仓库 2.基本配置,在application.yml中进行基本配置 参考类:AuthProperties 以下为例 fast: auth: # 默认所有的接口都需要鉴权,如需配置不需要鉴权的url 则在此以ant风格配置 antUrl: /o/**, /open/** # jwt有效期 单位:天 默认 expireDays: 5 # jwt生成的key secret: expireDays # 登陆地址 默认 loginUrl: login # 登陆方式 loginMethod: POST # 业务请求jwt key值 jwtHeaderKey: Authorization # 业务请求jwt value值前缀 jwtHeaderValueStart: Bearer 3.登陆 登陆,也就是认证,获取token签名,一般无非两个组成:登陆参数与登陆逻辑 3-1 登陆参数 现今各种系统登陆方式五花八门,比如手机号,用户名密码,邮箱等等。 抽象为接口:ILoginBo,如果你的登陆是username和password,那么可以使用默认实现类:DefaultLoginBo 如果不满足,请实现此接口自定义登陆参数类,例: @Data public class CustomLoginBo implements ILoginBo { private String username; private String password; //验证码 private String code; } 3-2 登陆逻辑 每个系统的登陆逻辑都不一样,请自定义类继承抽象类AbstractLoginAdapter,需要实现两个方法,例: public class CustomLogin extends AbstractLoginAdapter {//泛型要指定为登陆类 //指定登陆参数类的class 因为后面序列化需要用,回头会想想优化可以去掉此方法 @Override public Class getLoginBoClass() { return CustomLoginBo.class; } /** * 登陆逻辑 * @param loginBo 定义的登陆类 * @return JwtUser 登陆用户的信息 * @throws LoginException 登陆异常,请抛出此类,此类的 */ @Override public JwtUser login(CustomLoginBo loginBo) throws LoginException { if (loginBo.getUsername().equals("admin")) { //jwtUser类为指定的登陆用户信息类 JwtUser user = new JwtUser(); //请将用户信息放入detail 就像将用户信息放到servlet的session中 user.setDetails(loginBo); //设置用户所属的角色标识集合,一般为角色id,如果你的系统有角色,有部门,可以这样 role_角色id, dept_部门id user.setRoles(Arrays.asList(new String[]{"roleId"})); //登陆成功 return user; } else { //验证的地方,使用LoginException异常类,参数DefaultAuthResult 可以替换为你的项目定义的统一的接口返回值类 throw new LoginException(new DefaultAuthResult(300, "用户名不存在")); } } } 登陆成功,客户端会收到返回值登陆成功时,data值固定有user和token,details为你的用户model,roles为角色id集合, 至于最外层的data是固定key,code与msg,可以自定义,下文会有介绍 { "code": 0, "data": { "user": { "details": { "password": "admin", "username": "admin" }, "roles": [ "admin" ] }, "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJub25lIiwibmJmIjoxNTU3ODYyNTE1LCJpc3MiOiJub25lIiwib3duX3BhcmFtcyI6eyJyb2xlcyI6WyJhZG1pbiJdLCJkZXRhaWxzIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6ImFkbWluIn19LCJleHAiOjE1NTgzMjMzMTUsImlhdCI6MTU1Nzg2MjUxNX0.pp7Dn0u2x1e05KagE-7rOK2es9tjR_qqJ-IyVQ4a0Ew" }, "msg": "认证成功" } 4.访问业务接口 登陆成功后,如需访问业务接口,请在header中加入 Authorization,值为 Bearer + 上一步的token, 其中Authorization 与 Bearer,可通过配置文件自定义覆盖 5.鉴权 //需自定义类继承AbstractAuthAdapter抽象类 public class CustomAuth extends AbstractAuthAdapter { /** * 提供url所需权限 * @param url 请求的url */ @Override protected List getRolesByRequestUrl(String url, HttpServletRequest request, HttpServletResponse response) { //如无需url鉴权,请直接返回null return null; //如需鉴权,在此处根据url去数据库或者缓存中,查询到该url所对应的所有角色id集合 roleIdList,并返回 //框架会根据当前请求的用户角色集合与roleIdList是否有并集,有则通过,访问业务接口,无则返回权限错误 } } 6.返回值处理 因为不同的团队,不同系统,接口统一返回值格式各不一样,因此返回值这里也做了自定义扩展。 默认格式为: { "code": 0, "msg": "请求成功", "data": "业务数据" } 如果与你预期的不一致,可以自定义,但是data字段不允许自定义(后面会考虑优化) 可以将你的接口返回值类继承AuthResultAdapet类,加入你的自定义字段,可参考我写的默认实现: @Data public class DefaultAuthResult extends AuthResultAdapet { private int code; private String msg; public DefaultAuthResult() { super(null); } public DefaultAuthResult(int code, String msg) { super(null); this.code = code; this.msg = msg; } @Override public AuthResultAdapet loginSuccess() { return Contant.loginSuccess; } @Override public AuthResultAdapet loginFail() { return Contant.loginFail; } @Override public AuthResultAdapet noToken() { return Contant.noToken; } @Override public AuthResultAdapet acessDenied() { return Contant.acessDenied; } //此处为框架本身的几处需要返回值的地方 public static class Contant { public static final DefaultAuthResult loginSuccess = new DefaultAuthResult(0, "登陆成功"); public static final DefaultAuthResult loginFail = new DefaultAuthResult(103, "登陆失败"); public static final DefaultAuthResult noToken = new DefaultAuthResult(401, "请登陆"); public static final DefaultAuthResult acessDenied = new DefaultAuthResult(403, "凭证无效"); } } 7.启用,将刚才配置的三个类,加入容器中,即可启动测试: ``` @Configuration public class SecurityConfig extends WebSecurityConfig { @Bean public ILogin login() { return new CustomLogin(); } @Bean public IAuth auth() { return new CustomAuth(); } @Bean public AuthResultAdapet authResult(){ return new DefaultAuthResult(); } } ``` 以上为基本使用,项目中有demo,后面会进行优化,如有疑问,不足的地方,希望随时指出,共同进步。 #### 作者 luci yuyanan 邮箱:575873200@qq.com git:https://gitee.com/luci-fast/luci-fast-security