sa-token做登录验证

sa-token做登录验证

简介:sa-token是一个轻量级 java 权限认证框架,和spring security,shiro一样,能实现登录认证权限认证等功能,但使用上比spring security,shiro简单。本文主要简述sa-token的使用,以及登录认证及权限认证等操作。

1.引入maven依赖

		<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
		<dependency>
			<groupId>cn.dev33</groupId>
			<artifactId>sa-token-spring-boot-starter</artifactId>
			<version>1.37.0</version>
		</dependency>

2.配置application文件

默认为application.properties,我习惯使用application.yaml

server:
  # 端口
  port: 8080

############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
  # token 名称(同时也是 cookie 名称)
  token-name: satoken
  # token 有效期(单位:秒) 默认30天,-1 代表永久有效
  timeout: 2592000
  # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
  active-timeout: -1
  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
  is-concurrent: true
  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
  is-share: true
  # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
  token-style: uuid
  # 是否输出操作日志 
  is-log: true

只需要以上简单两步,即完成sa-token的引入

3.简单测试

创建简单的登录,验证测试接口

@RestController
@RequestMapping("/user/")
public class UserController {

    // 测试登录,浏览器访问: http://localhost:8081/user/doLogin?username=zhang&password=123456
    @RequestMapping("doLogin")
    public String doLogin(String username, String password) {
        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
        if("zhang".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001);
            return "登录成功";
        }
        return "登录失败";
    }

    // 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
    @RequestMapping("isLogin")
    public String isLogin() {
        return "当前会话是否登录:" + StpUtil.isLogin();
    }

}

在浏览器上访问http://127.0.0.1:8080/user/doLogin?username=zhang&password=123456,显示登录成功
在这里插入图片描述

接着在当前窗口修改连接访问http://127.0.0.1:8080/user/isLogin,显示登录状态:true
在这里插入图片描述

阶段性总结

以上已经实现sa-token的简单使用(登录认证),过程是

1.前端访问doLogin接口

2.后端验证账号密码正确后,通过调用sa-token的StpUtil.login(10001);接口实现登录,StpUtil.login(object)会创建key-value形式信息存储在服务端session中,然后通过set-cookie将浏览器当前会话的请求都带上satoken的sessionId。

3.当前页面会话的请求都会带上satoken的cookie,例如后面访问的isLogin接口,浏览器向后端请求isLogin接口

4.后端接收请求,通过调用StpUtil.isLogin();接口,后端在request的header中找是否存在satoken的cookie信息,找到后,获取其sessionId,也就是satoken的值,接着在服务端session中查找是否有该值,有则表示该请求是登录成功后的请求,返回登录认证成功。

4.前后端分离模式

看完上述流程,多次提到统一窗口,就知道上面的方式有其局限性,事实上,在前后端分离模式中,像当下很流行的vue,react,ajax+jquery等等,其每个请求都是独立的,可以理解为每个对后端的请求都相当于新开一个窗口。那这样通过以上方式(后端向前端设置cookie)就无法实现登录验证功能。

这个时候需要我们手动给每个需要认证登录的请求添加cookie

首先先从后端获取身份标识字符串,其实就是上面讲到的sessionId,后端将sessionId,下面成为tokenValue,返回给前端,服务端通过sa-token的StpUtil.getTokenInfo()获取到token的信息,其中关键有写进cookie的key-value,tokenValue的有效时间等等。

或者直接通过StpUtil.getTokenValue()只获取tokenValue也可以。

示例代码:

    @RequestMapping("doLogin")
    public String doLogin(String username, String password) {
        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
        if("zhang".equals(username) && "123456".equals(password)) {
            StpUtil.login(new User("10001","zhangsan"));
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return tokenInfo.toString();
        }
        return "登录失败";
    }

至于前端怎么设置cookie,添加请求头,此处不赘述,可以参考我的另一篇文章

vue2 引入Element UI和Axios

其中封装axios请求部分,中request.js文件有示例。

5.redis的引入

实现前后端分离后,再看看性能以及数据安全问题。

session是存储在服务端的,是跟springboot共用jvm空间的,多少会影响系统空间性能,但**更重要的是,如果Java项目shutdown,或者restart,那么存储在session中的登录信息将全部丢失,且无法寻回。**为了避免项目重启,登录信息失效,导致客户端集体需要重新登录,造成极坏的体验,我们应该将登录信息与系统解耦,并做持久化,所以考虑到引入redis

sa-token给我们提供了封装redis的sa-token依赖包,在上面的sa-token-spring-boot-starter依赖包的基础上添加sa-token-redis 或者 sa-token-redis-jackson

<!-- Sa-Token 整合 Redis (使用 jdk 默认序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis</artifactId>
    <version>1.37.0</version>
</dependency>

或者

<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.37.0</version>
</dependency>

以上无论哪种方式还需携带下面依赖

<!-- 提供Redis连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

然后在application.yaml中配置redis

spring: 
    # redis配置 
    redis:
        # Redis数据库索引(默认为0)
        database: 1
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器连接端口
        port: 6379
        # Redis服务器连接密码(默认为空)
        # password: 
        # 连接超时时间
        timeout: 10s
        lettuce:
            pool:
                # 连接池最大连接数
                max-active: 200
                # 连接池最大阻塞等待时间(使用负值表示没有限制)
                max-wait: -1ms
                # 连接池中的最大空闲连接
                max-idle: 10
                # 连接池中的最小空闲连接
                min-idle: 0

至此,redis配置完成,登录信息不需要手动存进redis,sa-token已经封装好,当我们调用StpUtil.login(object)的时候,sa-token会自动将登录信息存进redis,当调用getLoginId的时候则会将信息重新取出。

注意

在编码时发现一个坑,就是StpUtil.login(object)的时候,object如果是自定义对象类型,不能反序列化为自定义的对象(即使该自定义对象实现Serializable接口),例如用User类做参数,当getLoginId的时候不会返回User型,而是User类的toString字符串。

所以不要将用户对象作为LoginId,使用UserId做loginId就好了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值