首页 > 其他分享 >[solon]Solon开发实战之权限认证

[solon]Solon开发实战之权限认证

时间:2024-07-23 18:18:15浏览次数:11  
标签:solon 登录 import return token org Solon 权限

本项目采用权限认证框架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

QQ_1720958453295

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

QQ_1720958799830

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

登录认证相关接口

QQ_1720959669983

这些方法官方文档有介绍,写成接口方便查询和操作。比如退出登录、查询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)

QQ_1720961379643

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

集成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,登录,import,return,token,org,Solon,权限
From: https://www.cnblogs.com/mllt/p/18319262

相关文章

  • SpringBoot实战:Spring Boot接入Security权限认证服务
    引言SpringSecurity 是一个功能强大且高度可定制的身份验证和访问控制的框架,提供了完善的认证机制和方法级的授权功能,是一个非常优秀的权限管理框架。其核心是一组过滤器链,不同的功能经由不同的过滤器。本文将通过一个案例将 SpringSecurity 整合到 SpringBoot中,要实......
  • 易优CMS调用会员阅读权限的名称函数
    网站根目录extend/function.php文件内写入if(!function_exists('diy_getArcrank')){//显示文档的会员阅读权限名称functiondiy_getArcrank($arcrank=''){static$users_level_list=[];if(empty($users_level_list)){$users_lev......
  • RBAC权限模型概述
    RBAC即role-basedaccesscontrol,基于角色的访问控制通过角色来管理用户对系统资源的访问权限。RBAC是一种权限管理模型,核心思想是分离用户与具体权限,通过角色作为中介来实现用户与权限的关联RBAC的三个基本元素User:访问者Role:User和Permission的桥梁,他是权限的集合,用户通过被......
  • Python 中的 azure.ai.translation.document - 无法使用当前权限访问源文档位置
    我在使用Python中的azure.ai.translation.document库时遇到问题。我已经在Azure中设置了翻译服务以及带有两个容器的Blob存储。我已使用“用户委托密钥”创建了SAS连接。一种用于源(读取/列表),一种用于目标(写入/列表)。例如我尝试运行Python程序,但源b......
  • Python第九章(面向对象基础--属性,继承,dir查看,内存地址,权限等等和银行账户题目,圆的面积
    面向对象创造对象示例代码:类的名字用小驼峰命名法#编写Person类classPerson():passclassCat:#,小括号可以省略pass#对象名=类名per=Person()c=Cat()#小括号不能省略print(type(per))print(type(c))代码结果:<class'__main__.Person'><class'__mai......
  • PermissionError: [Errno 13] 权限被拒绝: 生产服务器上的“/root/.u2net”
    我正在使用rembg,它可以在我的本地计算机上运行,​​但在生产中会引发错误。所以我认为这与linux操作系统目录权限有关。这是服务器的完整日志:Traceback(mostrecentcalllast):File"/home/airnet-technologies-test-bgrm/htdocs/test-bgrm.airnet-technologies.com......
  • influxdb 查看和设置用户权限
    转载请注明出处:1.查看用户>SHOWUSERS运行示例:>SHOWUSERSuseradmin---------admintruereadonlyfalsemonitor_userfalse>2.创建用户CREATEUSER"myusername"WITHPASSWORD'mypassword'WITHALLPRIVILE......
  • 【攻防技术系列+权限维持】SUID后门
    在介绍linux提权的时候,曾说过SUID。什么是suid❓suid全称是SetownerUserIDuponexecution。这是Linux给可执行文件的一个属性,s标志。通俗的理解为其他用户执行这个程序的时候可以用该程序所有者/组的权限。需要注意的是,只有程序的所有者是0号或其他superuser,同时拥有su......
  • Win11 如何更改管理员权限,修改hosts内容
    一、找到hosts文件所在位置C:\Windows\System32\drivers\etc\hosts二、右键点击hosts,选择属性三、点击第二个安全,进入编辑界面四、点击添加,在最后一个窗口输入Everyone,单击确定五、出来之后第一个第一个页面相比之前多了Everyone,点击Everyone,在第二个窗口中的写入选项......
  • Jenkins(二)用户和权限配置
    一、点击系统管理—ConfigureGlobalSecurity 二、设置如下,保存后 页面右上角也会出现登录/注册的选项。   三、安装插件:Role-basedAuthorizationStrategy   四、点击系统管理,进入ManageandAssignRoles  五、点击ManageRoles进入角色管理......