一、网关鉴权
1.1 引入依赖
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-reactor-spring-boot3-starter</artifactId><version>1.39.0</version>
</dependency>
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-redis-jackson</artifactId><version>1.39.0</version>
</dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>
1.2 鉴权接口
package com.ozo.cloud.gateway.core;import cn.dev33.satoken.stp.StpInterface;
import com.ozo.cloud.common.base.context.CurrentUserHolder;
import com.ozo.cloud.common.base.model.LoginUser;import java.util.ArrayList;
import java.util.List;
public class SaPermissionImpl implements StpInterface {@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {LoginUser loginUser = CurrentUserHolder.current();return new ArrayList<>(loginUser.getMenuPermission());}@Overridepublic List<String> getRoleList(Object loginId, String loginType) {LoginUser loginUser = CurrentUserHolder.current();return new ArrayList<>(loginUser.getRolePermission());}}
1.3 过滤器配置
package com.ozo.cloud.gateway.config;import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.json.JSONUtil;
import com.ozo.cloud.common.base.model.ResultVO;
import com.ozo.cloud.gateway.config.properties.SecurityProperties;
import com.ozo.cloud.gateway.core.SaPermissionImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;
@EnableConfigurationProperties(SecurityProperties.class)
@Configuration
public class SaTokenConfig {@Autowiredprivate SecurityProperties securityProperties;@Beanpublic StpInterface stpInterface() {return new SaPermissionImpl();}@Beanpublic SaReactorFilter saServletFilter() {SaReactorFilter saReactorFilter = new SaReactorFilter();saReactorFilter.setBeforeAuth(obj -> {SaHolder.getResponse().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").setHeader("Access-Control-Allow-Headers", "*");SaRouter.match(SaHttpMethod.OPTIONS).free(r -> {}).back();}).setError(e -> {SaResponse saResponse = SaHolder.getResponse();saResponse.setHeader(Header.CONTENT_TYPE.getValue(), ContentType.JSON + ";charset=" + CharsetUtil.UTF_8);return JSONUtil.parseObj(ResultVO.fail(e.getMessage()));});saReactorFilter.addInclude("/**").setAuth(obj -> {SaRouter.match("/**", r -> StpUtil.checkLogin());});List<String> excludePathPatterns = securityProperties.getExcludePathPatterns();if (CollUtil.isNotEmpty(excludePathPatterns)) {saReactorFilter.addExclude(excludePathPatterns.toArray(new String[0]));}return saReactorFilter;}}
1.4 子服务添加Token
package com.ozo.cloud.gateway.filter;import cn.dev33.satoken.same.SaSameUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class ForwardAuthFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest newRequest = exchange.getRequest().mutate().header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken()).build();ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();return chain.filter(newExchange);}@Overridepublic int getOrder() {return 0;}}
二、子服务鉴权
2.1 引入依赖
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot3-starter</artifactId><version>1.39.0</version>
</dependency>
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-redis-jackson</artifactId><version>1.39.0</version>
</dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>
2.2 过滤器配置
package com.ozo.cloud.common.satoken.config;import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.same.SaSameUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.json.JSONUtil;
import com.ozo.cloud.common.base.model.ResultVO;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@AutoConfiguration
public class SaTokenConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");}@Beanpublic SaServletFilter getSaServletFilter() {return new SaServletFilter().addInclude("/**").setAuth(obj -> {SaSameUtil.checkCurrentRequestToken();}).setError(e -> {SaResponse saResponse = SaHolder.getResponse();saResponse.setHeader(Header.CONTENT_TYPE.getValue(), ContentType.JSON + ";charset=" + CharsetUtil.UTF_8);return JSONUtil.parseObj(ResultVO.fail(e.getMessage()));});}@Bean@ConditionalOnMissingBeanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}
2.3 拦截器
package com.ozo.cloud.common.satoken.interceptor;import cn.dev33.satoken.same.SaSameUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class FeignInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {requestTemplate.header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken());}}
2.4 接口使用拦截器
package com.ozo.cloud.api.auth.feign;import com.ozo.cloud.common.base.model.ResultVO;
import com.ozo.cloud.common.satoken.interceptor.FeignInterceptor;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "ozo-cloud-auth", path = "/auth", configuration = FeignInterceptor.class)
public interface AuthFeignClient {@GetMapping("/userInfo")ResultVO<Object> getUserInfo();}