本项目采用权限认证框架sa-tokensa-token-solon-plugin

pom.xml

<!--        鉴权-->
<dependency>
<groupId>org.noear</groupId>
<artifactId>sa-token-solon-plugin</artifactId>
</dependency>

配置

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

app.yml配置sa-token

登录认证

登录成功

相关资料:登录认证 (sa-token.cc)

首先是登录,登录成功了,调用StpUtil.login()方法,保存用户ID

该方法会自动生成token、token有效期等信息,和用户ID一起保存在Cookie当中

大致就是如上图这样的一些信息。

登录认证相关接口

这些方法官方文档有介绍,写成接口方便查询和操作。比如退出登录、查询token信息等等。


// 查询登录状态,浏览器访问: http://localhost:9420/sign/isLogin
@Mapping("/isLogin")
public String isLogin() {
return "当前会话是否登录:" + StpUtil.isLogin();
} /**
* 获取登录用户的id
* @return String
*/
@Mapping("/loginId")
public String loginId() {
return StpUtil.getLoginIdAsString();
} /**
* 获取登录用户的token
* @return String
*/
@Mapping("/loginToken")
public String loginToken() {
return StpUtil.getTokenValue();
} /**
* 退出登录
* @return String
*/
@Mapping("/logout")
public String isLogout() {
;
StpUtil.logout();
return loginId()+"退出登录";
} @Mapping("/token_timeout")
public Long getTokenTimeout(String account) {
return StpUtil.getTokenTimeout();
} /**
* 获取当前会话的 token 信息参数
* return
*/
@Mapping("/tokenInfo")
public SaTokenInfo getTokenInfo() {
return StpUtil.getTokenInfo();
}

路由拦截

相关参考资料:路由拦截鉴权 (sa-token.cc)

sa-token-solon-plugin和sa-token的写法可能会有一点区别。

这里使用的是sa-token-solon-plugin

首先注解是@Configuration

package cc.mllt.xrilang.WebConfig;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.solon.integration.SaTokenInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Filter;
import org.noear.solon.core.handle.FilterChain;
import org.smartboot.http.common.logging.Logger;
import org.smartboot.http.common.logging.LoggerFactory; @Configuration
public class AppFilter implements Filter { private static final Logger log = LoggerFactory.getLogger(AppFilter.class); @Bean
public SaTokenInterceptor saTokenInterceptor() {
return new SaTokenInterceptor()
.addInclude("/**/**")
.addExclude("/favicon.ico")
.addExclude("/sign/**")
.setAuth(req -> {
SaRouter.match("/**", StpUtil::checkLogin)
.match("/user/**", r -> StpUtil.checkPermission("user"))
.match("/admin/**", r -> StpUtil.checkPermission("admin"));
})
.setError(e -> {
log.error("未登录的非法请求。"+e.getMessage());
return "未登录";
})
.setBeforeAuth(req -> {
SaHolder.getResponse()
.setServer("xrilang-api-server")
.setHeader("X-Frame-Options", "SAMEORIGIN")
.setHeader("X-XSS-Protection", "1; mode=block")
.setHeader("X-Content-Type-Options", "nosniff");
});
} @Override
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
long start = System.currentTimeMillis();
try {
chain.doFilter(ctx);
if (!ctx.getHandled()) {
ctx.status(404);
ctx.output("Resource not found.");
}
} catch (Throwable e) {
ctx.status(500);
ctx.output(e.getMessage());
// 错误已经被 `setError` 方法记录,这里不再重复记录
}
long timeTaken = System.currentTimeMillis() - start;
log.info("Request processed in {} ms", timeTaken);
}
}

关键的地方在于

    public SaTokenInterceptor saTokenInterceptor() {
return new SaTokenInterceptor()
.addInclude("/**/**")
.addExclude("/favicon.ico")
.addExclude("/sign/**")
.setAuth(req -> {
SaRouter.match("/**", StpUtil::checkLogin)
.match("/user/**", r -> StpUtil.checkPermission("user"))
.match("/admin/**", r -> StpUtil.checkPermission("admin"));
})
.setError(e -> {
log.error("未登录的非法请求。"+e.getMessage());
return "未登录";
})
.setBeforeAuth(req -> {
SaHolder.getResponse()
.setServer("xrilang-api-server")
.setHeader("X-Frame-Options", "SAMEORIGIN")
.setHeader("X-XSS-Protection", "1; mode=block")
.setHeader("X-Content-Type-Options", "nosniff");
});
}

这个方法无需被调用。

配置好放行哪些,不放行哪些,错误返回信息就行。

Session会话

相关资料:Session会话 (sa-token.cc)

具体使用方法以后再更新。

集成redis

参考资料:集成 Redis (sa-token.cc)

这里使用官方文档的第二种方式集成redis

所有pom.xml现在是

<!--        鉴权-->
<dependency>
<groupId>org.noear</groupId>
<artifactId>sa-token-solon-plugin</artifactId>
</dependency>
<!--鉴权-redis-序列化-->
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version> 1.38.0</version>
</dependency>
<!-- Jackson 的 JSR310 支持模块 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version> 2.17.2</version>
</dependency>
<!-- 提供Redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version> 2.11.1</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version> 3.21.3</version>
</dependency>

然后配置redis连接信息

集成 Redis 后,是我额外手动保存数据,还是框架自动保存?

框架自动保存。集成 Redis 只需要引入对应的 pom依赖 即可,框架所有上层 API 保持不变。

我是创建了一个RedisConfig.java文件,代码如下

package cc.mllt.xrilang.WebConfig;

import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.solon.dao.SaTokenDaoOfRedissonJackson;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.smartboot.http.common.logging.Logger;
import org.smartboot.http.common.logging.LoggerFactory; @Configuration
public class RedisConfig {
static Logger log = LoggerFactory.getLogger(RedisConfig.class); @Inject(value="${redis.host}", autoRefreshed = true)
private String host; @Inject(value="${redis.port}", autoRefreshed = true)
private int port; // @Inject(value="${redis.password}", autoRefreshed = true)
// private String password; @Bean
public RedissonClient redissonClient() {
try {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://" + host + ":" + port)
.setDatabase(1); // 使用配置中的数据库索引
// .setPassword(password);
RedissonClient redisson = Redisson.create(config);
log.info("连接redis成功");
return redisson;
}catch (Exception e){
log.error("连接redis失败,请检查Redis配置信息并先启动redis", e);
return null;
}
} @Bean
public SaTokenDao saTokenDao(RedissonClient redissonClient) {
return new SaTokenDaoOfRedissonJackson(redissonClient);
}
}

[solon]Solon开发实战之权限认证的更多相关文章

  1. Django 中使用权限认证

    权限认证 权限概念 """ 在实际开发中,项目中都有后台运营站点,运营站点里面会存在多个管理员, 那么不同的管理员会具备不同的任务和能力,那么要实现这样的管理员功能,那么 ...

  2. Solon Web 开发,七、视图模板与Mvc注解

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  3. thinkphp5的Auth权限认证实战

    thinkphp5的Auth权限认证实战 一.总结 一句话总结:基于角色的权限管理(真正做一遍,就会发现很简单,不然一直都是半懂不懂的) 角色 权限 真正做一遍,就会发现很简单,不然一直都是半懂不懂的 ...

  4. Hangfire实战二——为DashBoard页面添加权限认证

    概述 Hangfire Dashboard为我们提供了可视化的对后台任务进行管理的界面,我们可以直接在这个页面上对定时任务进行删除.立即执行等操作,如下图所示: 默认情况下,这个页面只能在部署Hang ...

  5. Solon Web 开发

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  6. Solon Web 开发,一、开始

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  7. Solon Web 开发,二、开发知识准备

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  8. Solon Web 开发,四、请求上下文

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  9. Solon Web 开发,五、数据访问、事务与缓存应用

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  10. Solon Web 开发,六、过滤器、处理、拦截器

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

随机推荐

  1. duxui:基于Taro,兼容React Native、小程序、H5的多端UI库

    duxui是duxapp官方开发的一款兼容多端的UI组件库,兼容小程序.H5.React Native,库中提供了60+的组件,覆盖大部分使用场景 它能帮助你通过统一的组件样式,快速完成多端应用的开发 ...

  2. eBPF 概述:第 4 部分:在嵌入式系统运行

    1. 前言 在本系列的第 1 部分和第 2 部分,我们介绍了 eBPF 虚拟机内部工作原理,在第 3 部分我们研究了基于底层虚拟机机制之上开发和使用 eBPF 程序的主流方式. 在这一部分中,我们将从 ...

  3. linux overlay文件系统

    一个 overlay 文件系统包含两个文件系统,一个 upper 文件系统和一个 lower 文件系统,是一种新型的联合文件系统.overlay是"覆盖-上面"的意思,overla ...

  4. 多款国产操作系统安装数据库干货文档汇总(含Oracle/MySQL/国产数据库等)

    随着国产化的逐步推进,越来越多的企业选择将数据库安装在国产操作系统上.为帮助大家了解国产操作系统上的数据库成功搭建案例与搭建方式,本文整理了墨天轮数据技术社区上用户分享的实操文档,涵盖银河麒麟.中标麒 ...

  5. KubeSphere DevOps 系统功能实战

    James,Java 工程师,喜欢学习和记录当下热门技术并验证其优势和缺点,以及当下火热的云原生解决方案的实施与推广. 前言 基于 Jenkins 的 KubeSphere DevOps 系统是专为 ...

  6. 自学PHP笔记(一) PHP语法

    本文转发来自:https://blog.csdn.net/KH_FC/article/details/115407577 PHP基本语法 php使用一对特殊的标记包含php代码,与HTML代码混在一起 ...

  7. Chrome使用回退,出现表单提交失败,ERR_CACHE_MISS问题

    是什么.为什么.怎么办 "ERR_CACHE_MISS" 错误通常发生在你使用浏览器的"返回"按钮时.这种错误与浏览器处理缓存数据的方式有关,特别是在处理表单和 ...

  8. 工作中的技术总结_JAVA_AA-00001 关于Session的使用 _20210825

    AA-00001 关于Session的使用 _20210825 Session Java 中的Session:javax.servlet.http.HttpSession; 应用: 在我自己的项目中 ...

  9. 根据字符串,获取实体属性上的annotation,如:createTime” 找到对应实体属性中的 TableField(value = "create_time", fill = FieldFill.INSERT)

    根据字符串,获取实体属性上的annotation,如:createTime" 找到对应实体属性中的 TableField(value = "create_time", f ...

  10. Windows平台安装MongoDB步骤以及问题处理

    今天开始向MongoDB进军,结果一开始就给我来了个下马威--安装不成功,死在了第一步,我滴个乖乖,哪能服气,为了不让后面的小伙伴踩坑,特此记录,希望能帮到有需要的小伙伴. 一.安装步骤 1.下载安装 ...