spring boot3 二、 spring alibaba cloud 整合 sa-token redis

在这里插入图片描述

jm-apis-common pom.xml

        <!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--        sa-token-->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot3-starter</artifactId>
        </dependency>
        <!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-dao-redis-jackson</artifactId>
        </dependency>

jm-user-api bootstrap-dev.yml

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        namespace: f5d53f37-d171-43c7-9b77-01c64eeae769
      config:
        namespace: f5d53f37-d171-43c7-9b77-01c64eeae769
        extension-configs:
          - dataId: jm-user-api.yaml
            refresh: true
        shared-configs:
          - dataId: jm-redis.yaml
            refresh: true
          - dataId: jm-token.yaml
            refresh: true

jm-user-api jm-token.yaml

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

jm-gateway pom.xml

       <!--sa-token-->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-reactor-spring-boot3-starter</artifactId>
        </dependency>

        <!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

jm-gateway RedisConf.java

package com.jm.gateway.conf;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis相关配置
 *
 * @author lime
 */
@Configuration
@EnableRedisRepositories
public class RedisConf {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        Jackson2JsonRedisSerializer<?> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}

jm-gateway SaTokenConf.java 网关sa-token配置

package com.jm.gateway.conf;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.router.SaRouterStaff;
import cn.dev33.satoken.stp.StpUtil;
import com.jm.gateway.bean.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * [Sa-Token 权限认证] 配置类
 *
 * @author kong
 */
@Slf4j
@Configuration
public class SaTokenConf {
    private final RedisTemplate<String, Object> redis;
    private final SecureConf secureConf;

    @Autowired
    public SaTokenConf(RedisTemplate<String, Object> redis, SecureConf secureConf) {
        this.redis = redis;
        this.secureConf = secureConf;
    }


    /**
     * 注册 Sa-Token全局过滤器
     */
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址
                .addInclude("/**").addExclude(secureConf.getApiWhiteUris().toArray(new String[0]))
                // 鉴权方法:每次访问进入
                .setAuth(obj -> {
                    SaRequest request = SaHolder.getRequest();
                    // 登录校验 -- 拦截所有路由,开放登录接口
                    SaRouterStaff routerStaff = SaRouter.match("/**", "/user/api/open/**", r -> StpUtil.checkLogin());
                    if (routerStaff.isHit) {
                        String token = request.getHeader("token");
                        if (StringUtils.isBlank(token)) {
                            token = request.getParam("token");
                        }
                    }
                })
                // 异常处理方法:每次setAuth函数出现异常时进入
                .setError(e -> Result.fail(e.getMessage()))
                // 前置函数:在每次认证函数之前执行
                .setBeforeAuth(o -> this.configCross());
    }


    /**
     * 配置跨域
     */
    private void configCross() {
        // ---------- 设置跨域响应头 ----------
        SaHolder.getResponse()
                // 是否可以在iframe显示视图: DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
                .setHeader("X-Frame-Options", "SAMEORIGIN")
                // 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面
                .setHeader("X-XSS-Protection", "1; mode=block")
                // 禁用浏览器内容嗅探
                .setHeader("X-Content-Type-Options", "nosniff")
                // 允许指定域访问跨域资源
                .setHeader("Access-Control-Allow-Origin", "*")
                // 允许所有请求方式
                .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
                // 有效时间
                .setHeader("Access-Control-Max-Age", "3600")
                // 允许的header参数
                .setHeader("Access-Control-Allow-Headers", "*");

        // 如果是预检请求,则立即返回到前端
        SaRouter.match(SaHttpMethod.OPTIONS).free(r -> log.warn("--------OPTIONS预检请求,不做处理")).back();
    }

}

jm-gateway SecureConf .java 在配置中心配置权限

package com.jm.gateway.conf;

import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 网关白名单配置
 *
 * @author lime
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Component
@ConfigurationProperties(prefix = "secure")
public class SecureConf {
    /**
     * 限制ip每秒访问次数
     */
    private Long limitIpSecondCount;
    private Long limitIpMinuteCount;
    private Long limitIpHourCount;
    /**
     * ip 白名单
     */
    private List<String> ipWhites;
    /**
     * ip黑名单
     */
    private List<String> ipBlacks;
    /**
     * 白名单
     */
    private List<String> apiWhiteUris;
    /**
     * xss 黑名单
     */
    private List<String> xssBlackUris;
}

完整代码请看项目git地址

https://gitee.com/sunuping/jianmu-example-jdk17.git
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等一场春雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值