权限框架RABC--sa-tokne实践

100 阅读3分钟

主要就是创建一个项目,引入,然后测试效果,sa-token 的网址:[在 SpringBoot 环境集成 - Sa-Token (dev33.cn)](links.jianshu.com/go?to=https… token.dev33.cn%2Fdoc%2Findex-backup.html%23%2Fstart%2Fexample "在 SpringBoot 环境集成 - Sa-Token (dev33.cn)")

第一步创建一个项目springboot,完整pom如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.auth</groupId>
    <artifactId>token</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>token</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.23</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
            <version>1.29.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-crypto</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.17</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.jimmyshi</groupId>
            <artifactId>bean-query</artifactId>
            <version>1.1.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

第二步 添加yml配置文件,完整pom 如下

server:
  port: 8081
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://10.0.59.65:3307/graph?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 配置初始化大小、最小、最大
      initial-size: 5
      minIdle: 10
      max-active: 20
      # 配置获取连接等待超时的时间(单位:毫秒)
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 2000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 600000
      max-evictable-idle-time-millis: 900000
      # 用来测试连接是否可用的SQL语句,默认值每种数据库都不相同,这是mysql
      validationQuery: select 1

# Sa-Token配置
sa-token:
  # token名称 (同时也是cookie名称)
  token-name: token
  # token有效期,单位s 默认30天, -1代表永不过期
  timeout: 86400
  # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
  activity-timeout: -1
  # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
  is-concurrent: true
  # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
  is-share: true
  # token风格
  token-style: uuid
  # 是否输出操作日志
  is-log: false
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

引入重要的两个配置文件

mvc 拦截器配置

/**
 * @ClassName: SaTokenConfigure
 */

import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.interceptor.SaRouteInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


@Component
public class SaTokenConfigure implements WebMvcConfigurer {

    //放行路径
    private static final String[] EXCLUDE_PATH_PATTERNS = {
        "**/swagger-ui.html",
        "/swagger-resources/**",
        "/webjars/**",
        "/v3/**",
        "/swagger-ui.html/**",
        "/swagger-ui/**",
        "/swagger-ui/index.html#/**",
        "/doc.html/**",
        "/error",
        "/favicon.ico",
        "sso/auth",
        "/csrf",
        "/user/add",
        "/user/reset",
        "/user/edit"
    };
    // 注册Sa-Token的注解拦截器,打开注解式鉴权功能
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 注册注解拦截器,并排除不需要注解鉴权的接口地址 (与登录拦截器无关)
        registry.addInterceptor(new SaRouteInterceptor((req, res, handler) -> {
            // 登录认证 -- 拦截所有路由,并排除/user/login 用于开放登录
            SaRouter.match("/**", "/user/login", r -> StpUtil.checkLogin());

        })).addPathPatterns("/**").excludePathPatterns(EXCLUDE_PATH_PATTERNS);
        // 开启aop校验权限
        registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
        // 续约token
        registry.addInterceptor(new AuthInfoInterceptor()).addPathPatterns("/**");
    }


}

个人权限集合,角色集合

@Component
@Configurationpublic class StpInterfaceConfig implements StpInterface {

    @Resource
    private AuthUserDao authUserDao;

    @Autowired
    private AuthMenuService authMenuService;

    @Autowired
    private AuthRoleMenuService authRoleMenuService;

    @Autowired
    private AuthRoleService authRoleService;


    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        AuthUser authUser = this.authUserDao.queryById(Integer.parseInt(loginId.toString()));
        if (ObjectUtil.isNull(authUser)) {
            throw new GraphExecuteException("用户不存在");
        }
        AuthRole authRole = authRoleService.queryById(authUser.getRoleId());
        if (ObjectUtil.isNull(authRole)) {
            throw new GraphExecuteException("角色不存在");
        }

        // 所有操作权限
        List<AuthMenu> menuList = authMenuService.queryAll();
        List<String> menuCodeList;
        if (RoleEnum.SYSTEM.name().equals(authRole.getType())) {
            menuCodeList = menuList.stream().map(AuthMenu::getMenuCode).collect(Collectors.toList());
        } else {
            menuCodeList = authRoleMenuService.queryByRoleId(authRole.getId());
        }

        return menuCodeList;
    }

    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        return new ArrayList<String>();
    }
}

接下来开始一个一个尝试, 登录认证, token续约, 踢人下线, 拦截鉴权,aop权限认证

@Override
    public Map doLogin(String username, String password) {
        AuthUser authUser = authUserDao.queryByName(username);
        if (ObjectUtil.isNull(authUser)) {
            throw new GraphExecuteException("用户不存在!");
        }

        if (ObjectUtil.notEqual(authUser.getPassword(), SecureUtil.md5(password))) {
            throw new GraphExecuteException("用户名密码不正确!");
        }
        StpUtil.login(authUser.getId());
        SaTokenInfo saTokenInfo = StpUtil.getTokenInfo();
        String token = saTokenInfo.getTokenValue();
        long tokenTimeout = saTokenInfo.getTokenTimeout();
        authUser.setPassword("");
        HashMap<Object, Object> res = new HashMap<>();
        res.put("token", token);
        res.put("tokenTimeout", tokenTimeout);
        res.put("info", authUser);
        return res;
    }

续约

/**
 * @ClassName: AuthInfoInterceptor
 */
@Slf4j
public class AuthInfoInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //String tenantId = request.getHeader(TenantEnum.SYSTEM_TENANT_ID.getName());
        //log.info(">>>>>>>拦截到api相关请求头<<<<<<<<" + tenantId);
        //if (!StringUtils.isEmpty(tenantId)) {
        //    //直接搂下来,放到ThreadLocal中 后续直接从中获取
        //    CurrentLocal.set(TenantEnum.SYSTEM_TENANT_ID.getName(), tenantId);
        //}
        // 续约token
        if (StpUtil.getTokenTimeout() <= StpUtil.getTokenActivityTimeout()) {
            StpUtil.renewTimeout(1800);
        }
        return true;//注意 这里必须是true否则请求将就此终止。
    }


    @Override

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //移除app-user
        //CurrentLocal.remove(TenantEnum.SYSTEM_TENANT_ID.getName());
    }

}

鉴权示例, 可以在表中增加相应菜单的相应权限码,在此控制

@SaCheckPermission("usermgt") // 接口鉴权示例
    @PostMapping("/page")
    @ApiOperation("分页查询用户信息")
    public R<PageInfo<AuthUserPageVo>> queryByPage(@RequestBody UserQueryByPageDto userQueryByPageDto) {
        return R.data(this.authUserService.queryByPage(userQueryByPageDto));
    }

快快自己手动尝试吧,这个框架nice的狠, 集成各种单点登录 seucrity, autho2 都ok啦

本文转自 jimolvxing.blog.csdn.net/article/det…,如有侵权,请联系删除。