一、网关鉴权
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 {
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
LoginUser loginUser = CurrentUserHolder.current();
return new ArrayList<>(loginUser.getMenuPermission());
}
@Override
public 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 {
@Autowired
private SecurityProperties securityProperties;
@Bean
public StpInterface stpInterface() {
return new SaPermissionImpl();
}
@Bean
public 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 {
@Override
public 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);
}
@Override
public 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 {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor())
.addPathPatterns("/**");
}
@Bean
public 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
@ConditionalOnMissingBean
public 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 {
@Override
public 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();
}