• Stars
    star
    125
  • Rank 285,261 (Top 6 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created over 5 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Light Security是一个基于jwt的权限控制框架,支持与Spring Boot配合使用,支持Spring MVC与WebFlux

Light Security

Light Security是一款基于 jwt 的、简洁而不简单的权限控制框架,可与 Spring Boot 配合使用,支持 Spring MVCWebFlux

地址

特点

优点

  • 上手快速
  • 开箱即用
  • 轻量级,代码精简,不到500行代码
  • 功能实用,市面上安全框架常见能力与套路均已具备
    • 支持 RESTful 权限控制
    • 支持灵活的权限配置(代码配置方式优先级更高)
      • 支持基于配置文件的权限配置
      • 支持基于代码的权限控制
    • 支持基于注解的权限控制
  • 设计简单,没有复杂概念;
    • Spring Web编程模型
      • 基于权限配置的方式:核心是1个拦截器
      • 基于注解的权限控制:核心是1个切面
    • WebFlux编程模型
      • 基于权限配置的方式:核心是1个过滤器
      • 基于注解的权限控制:核心是1个切面

缺点

  • 功能
    • 比 Spring Security 弱一点
    • 和Shiro比功能差不多,但没有实现复杂的Authentication Strategy(想实现也很简单,详见扩展点)
  • 只考虑权限相关问题
    • 不考虑身份认证(登录),意味着登录逻辑得自己玩;
    • 不考虑防攻击,意味着网络攻击得自己防;

依赖

  • Spring MVC:用到Spring MVC的拦截器,如只使用基于注解的权限控制,则无需该部分依赖;
  • Spring WebFlux:用到WebFlux的Filter,如只使用基于注解的权限控制,则无需该部分依赖;
  • Spring AOP:如果不用基于注解的权限控制,则无需该部分依赖;
  • jwt:你懂的

快速上手

Spring Web编程模型

TIPS

快速上手可详见项目 light-security-example 目录,内附详细测试步骤。

基于配置文件的权限配置

  • 加依赖:

    <dependency>
        <groupId>com.itmuch.security</groupId>
        <artifactId>light-security-spring-boot-starter</artifactId>
        <version>1.1.0-RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
  • 写配置

    server:
      port: 8009
    light-security:
      # 权限规则配置:表示用{http-method}方法请求的{path}路径必须具备什么{expression}
      spec-list:
        - http-method: ANY
          path: /login
          expression: "anon()"
        - http-method: ANY
          path: /user
          expression: "hasAnyRoles('user','admin')"
        - http-method: ANY
          path: /user-no-access
          expression: "hasAllRoles('user','admin','xx')"
        - http-method: GET
          path: /error
          expression: "anon()"
        - http-method: ANY
          path: /**
          expression: "hasLogin()"
      jwt:
        # jwt sign算法
        algorithm: hs512
        # jwt secret
        secret: {secret}
        # jwt 有效时间
        expiration-in-second: 1209600
  • 写代码:

    @RequestMapping
    @RestController
    @RequiredArgsConstructor(onConstructor = @__(@Autowired))
    public class TestController {
        private final UserOperator userOperator;
        private final JwtOperator operator;
    
        /**
         * 演示如何获取当前登录用户信息
         * - 该路径需要具备user或admin权限才可访问,详见application.yml
         *
         * @return 用户信息
         */
        @GetMapping("/user")
        public User user() {
            return userOperator.getUser();
        }
    
        @GetMapping("/user-no-access")
        public User userNoAccess() {
            return userOperator.getUser();
        }
    
        /**
         * 演示基于注解的权限控制
         *
         * @return 如果有权限返回 亲,你同时有user、admin角色..
         */
        @GetMapping("/annotation-test")
        @PreAuthorize("hasAllRoles('user','admin')")
        public String annotationTest() {
            return "亲,你同时有user、admin角色..";
        }
    
        @GetMapping("/annotation-test-no-access")
        @PreAuthorize("hasAllRoles('user','admin','xx')")
        public String annotationTestNoAccess() {
            return "亲,你同时有user、admin、xx角色..";
        }
    
        /**
         * 模拟登录,颁发token
         *
         * @return token字符串
         */
      @GetMapping("/login")
        public String loginReturnToken() {
            User user = User.builder()
                    .id(1)
                    .username("张三")
                    .roles(Arrays.asList("user", "admin"))
                    .build();
            return operator.generateToken(user);
        }
    }

基于代码的权限配置

@Configuration
public class LightSecurityConfigurtion {
    @Bean
    public SpecRegistry specRegistry() {
        return new SpecRegistry()
                .add(HttpMethod.GET, "/user", "hasAnyRoles('user')")
                .add(HttpMethod.ANY, "/**", "hasLogin()");
    }
}

此时,application.yml 中的如下配置可删除,因为代码配置方式优先级更高,配置文件方式将会失效

light-security:
  # 权限规则配置:表示用{http-method}方法请求的{path}路径必须具备什么{expression}
  spec-list:
    - http-method: ANY
      path: /login
      expression: "anon()"
    - http-method: ANY
      path: /user
      expression: "hasAnyRoles('user','admin')"
    - http-method: ANY
      path: /user-no-access
      expression: "hasAllRoles('user','admin','xx')"
    - http-method: GET
      path: /error
      expression: "anon()"
    - http-method: ANY
      path: /**
      expression: "hasLogin()"

扩展点

作用
com.itmuch.lightsecurity.jwt.UserOperator 提供用户相关操作,例如解析token获得用户信息等。
com.itmuch.lightsecurity.el.PreAuthorizeExpressionRoot 提供表达式支持,例如hasAnyRoles('user') 等,如需新能力,只需编写新方法即可
com.itmuch.lightsecurity.annotation.support.PreAuthorizeAspect 为注解 @PreAuthorize("hasAllRoles('user','admin')")提供支持

WebFlux编程模型

TIPS

快速上手可详见项目 light-security-webflux-example 目录,内附详细测试步骤。

基于配置文件的权限配置

  • 加依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
      <groupId>com.itmuch.security</groupId>
      <artifactId>light-security-webflux-spring-boot-starter</artifactId>
      <version>1.1.0-RELEASE</version>
    </dependency>
  • 写配置

    server:
      port: 8009
    light-security:
      # 权限规则配置:表示用{http-method}方法请求的{path}路径必须具备什么{expression}
      spec-list:
        - http-method: ANY
          path: /login
          expression: "anon()"
        - http-method: ANY
          path: /user
          expression: "hasAnyRoles('user','admin')"
        - http-method: ANY
          path: /user-no-access
          expression: "hasAllRoles('user','admin','xx')"
        - http-method: GET
          path: /error
          expression: "anon()"
        - http-method: ANY
          path: /**
          expression: "hasLogin()"
      jwt:
        # jwt sign算法
        algorithm: hs512
        # jwt secret
        secret: {secret}
        # jwt 有效时间
        expiration-in-second: 1209600
  • 写代码

    @RequestMapping
    @RestController
    @RequiredArgsConstructor(onConstructor = @__(@Autowired))
    public class TestController {
        private final ReactiveUserOperator userOperator;
        private final JwtOperator operator;
    
        /**
         * 演示如何获取当前登录用户信息
         * - 该路径需要具备user或admin权限才可访问,详见application.yml
         *
         * @return 用户信息
         */
        @GetMapping("/user")
        public Mono<User> user() {
            return userOperator.getUser();
        }
    
        @GetMapping("/user-no-access")
        public Mono<User> userNoAccess() {
            return userOperator.getUser();
        }
    
        /**
         * 演示基于注解的权限控制
         *
         * @return 如果有权限返回 亲,你同时有user、admin角色..
         */
        @GetMapping("/annotation-test")
        @PreAuthorize("hasAllRoles('user','admin')")
        public Mono<String> annotationTest() {
            return Mono.just("亲,你同时有user、admin角色..");
        }
    
        @GetMapping("/annotation-test-no-access")
        @PreAuthorize("hasAllRoles('user','admin','xx')")
        public Mono<String> annotationTestNoAccess() {
            return Mono.just("亲,你同时有user、admin、xx角色..");
        }
    
        /**
         * 模拟登录,颁发token
         *
         * @return token字符串
         */
        @GetMapping("/login")
        public String loginReturnToken() {
            User user = User.builder()
                    .id(1)
                    .username("张三")
                    .roles(Arrays.asList("user", "admin"))
                    .build();
            return operator.generateToken(user);
        }
    }

基于代码的权限配置

@Configuration
public class LightSecurityConfigurtion {
    @Bean
    public SpecRegistry specRegistry() {
        return new SpecRegistry()
                .add(HttpMethod.GET, "/user", "hasAnyRoles('user')")
                .add(HttpMethod.ANY, "/**", "hasLogin()");
    }
}

此时,application.yml 中的如下配置可删除,因为代码配置方式优先级更高,配置文件方式将会失效

light-security:
  # 权限规则配置:表示用{http-method}方法请求的{path}路径必须具备什么{expression}
  spec-list:
    - http-method: ANY
      path: /login
      expression: "anon()"
    - http-method: ANY
      path: /user
      expression: "hasAnyRoles('user','admin')"
    - http-method: ANY
      path: /user-no-access
      expression: "hasAllRoles('user','admin','xx')"
    - http-method: GET
      path: /error
      expression: "anon()"
    - http-method: ANY
      path: /**
      expression: "hasLogin()"

扩展点

作用
com.itmuch.lightsecurity.jwt.ReactiveUserOperator 提供用户相关操作,例如解析token获得用户信息等。
com.itmuch.lightsecurity.el.ReactivePreAuthorizeExpressionRoot 提供表达式支持,例如hasAnyRoles('user') 等,如需新能力,只需编写新方法即可
com.itmuch.lightsecurity.annotation.support.ReactivePreAuthorizeAspect 为注解 @PreAuthorize("hasAllRoles('user','admin')")提供支持

常见问题

为什么要造这个轮子?

老是有人问我诸如"微服务安全怎么管理?"、"Spring Security xxxx问题你遇到过吗?"、"能写个Spring Cloud Security的系列教程吗?"、"Shiroxxxx问题你遇到过吗?"

烦不胜烦,初期积极回复;后来消极回复;再后来懒得回复。

分析一下,发现主要原因还是Spring Security、Shiro学习曲线较高,特别是Spring Security。所以就想写个轻量的框架,能够快速解决主要矛盾——足够简单、能实现权限控制。

为什么不考虑身份认证(登录)?

目前市面上大多权限框架都考虑了"身份认证(登录)" + "权限管理" 。然而登录操作在现在这个时代,是一个"五花八门"的操作。例如:

  • 手机号 + 验证码登录
  • 扫二维码登录
  • 账号密码登录
  • 证书登录

往往还需还同时支持多种登录方式。这挺难去抽象出通用模式,并为典型的登录方式提供支持。

索性不考虑了——把登录问题留给使用者自己。用户可根据业务需求实现登录逻辑,并颁发Token,后面的事情就交给 Light Security ,让它给你搞定。这样相对更加灵活,更重要的是——你也不再需要去学习用框架应该怎么登录。

TODO

  • 支持对称加密/非对称加密配置化;
  • 支持 JWE
  • 补充单元测试
  • 将框架与starter分离,否则既是框架,又是Starter感觉有点怪。

More Repositories

1

spring-cloud-study

开源书《跟我学Spring Cloud》的配套代码。讨论QQ群:731548893
Java
1,043
star
2

spring-cloud-book

《使用Spring Cloud与Docker实战微服务》开源书。讨论QQ群:731548893。配套代码:https://github.com/eacdy/spring-cloud-study
913
star
3

awesome-spring-cloud

Spring Cloud 优质资源一网打尽
271
star
4

itmuch-miniapp

IT牧场小程序前端代码,使用mpvue + vant-weapp构建。本项目仅供教学使用,如果前端基础不好的同学,可以直接放弃。不影响Spring Cloud Alibaba的学习。
Vue
208
star
5

spring-cloud-yes

基于Spring Cloud的快速开发脚手架&最佳实践总结
Java
168
star
6

awesome-idea

IntelliJ IDEA资源一网打尽
160
star
7

Sentinel-Dashboard-Nacos

Description Sentinel Dashboard使用NACOS作为数据源持久化规则。【仅用于教学,如用于生产,请务必做好测试!】
Java
100
star
8

spring-cloud-wii

An easy way to integrate polyglot apps for Spring Cloud.
Java
76
star
9

spring-boot-study

Spring Boot技术栈示例代码,手把手快速上手教程。
Java
54
star
10

spring-cloud-docker-study

Spring Cloud 与 Docker 整合使用示例,为《使用Spring Cloud与Docker实战微服务》的配套代码。书籍地址:https://github.com/eacdy/spring-cloud-book 。讨论QQ群:157525002(已满)、564840207,欢迎加入。
Java
41
star
11

redis-jdbc

A JDBC Driver for Redis which is based on Jedis.
Java
33
star
12

awesome-chrome-plugins

牛逼的Chrome插件
18
star
13

spring-boot-yes

Spring Boot YES,一个轻量级的、基于Spring Boot的开发脚手架,迅速上手,迅速开发。
Java
6
star