gateWay 结合 nacos 完成 jwt验证

1. 安装nacos 2.1.2

下载ubuntu版的nocos,传到服务器,并解决。

  1.1首先安装jdk:  apt-get install openjdk-8-jdk

  1.2 进行bin目录启动nacos:  bash startup.sh -m standalone

  1.3 根据输出日志 找到启动路径

 

2.开发gateWay

2.1 配置pom.xml

<dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<!--                        <version>2021.1</version>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <!--                        <version>2021.1</version>-->
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.18.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter
          不引入spring-boot-starter-jdbc 会报错-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>

        <!--fegin组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- Feign Client for loadBalancing -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
    </dependencies>

 这个版本nacos 一定要需要fegin组件,虽然用不到,不然做gateway路由的时候,会提示503,死活转发到后面的服务(uri使用lb://iotServer,如果使用真实地址是没有问题)。

server:
  port: 8888 #网关地址
spring:
  profiles:
    active: dev
  application:
    name: gateway #服务名称
  cloud:
    nacos:
      server-addr:  192.168.56.101:8848
    gateway:
      routes:
        - id: iotServer
#          uri: http://127.0.0.1:8099/
          uri: lb://iotServer #路由目的地址
          predicates:
            - Path=/kaying/v1/huabang/**  #遇到这样的url进行拦截与转发

jwt代码

//@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter , Ordered {

    @Autowired
    AuthorizeDao dao;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String requestUrl = exchange.getRequest().getURI().getPath();/*获取请求地址 财哥 2022/10/31 8:15*/
        System.out.println("开始拦截");
        System.out.println(requestUrl);
        MultiValueMap<String,String> params = exchange.getRequest().getQueryParams();/*获取参数列表 财哥 2022/10/31 8:20*/

        String loginUrl = "/kaying/v1/huabang/login";
        if(loginUrl.equals(requestUrl)){/*进行身份验证 财哥 2022/10/31 8:17*/
                if(!params.containsKey("userCode")){
                    JSONObject json = new JSONObject();
                    json.put("desc","用户名不能为空");
                    json.put("code","401");
                    return returnJsonResult(exchange,json.toJSONString());
                }
                String userCode = params.getFirst("userCode");
                String password = params.getFirst("password");
                //查数据库进行匹配
                Map<String, Object> userMap = dao.queryForMap(String.format("select * from hb_user where user_code='%s' and user_pwd='%s' and is_job='1'",userCode,password));
                if(userMap != null){
                    User user = new User();
//                    user.setUserName(userMap.get("user_name").toString());
                    user.setUserCode(userMap.get("user_code").toString());
                    user.setUserPwd(userMap.get("user_pwd").toString());
                    String token = JwtUtils.getToken(user);/*获取token 财哥 2022/10/31 13:04*/
                    exchange.getResponse().setStatusCode(HttpStatus.OK);
                    exchange.getResponse().getHeaders().set("Authorization",token);
                }else{
                    JSONObject json = new JSONObject();
                    json.put("desc","用户名或密码错误");
                    json.put("code","401");
                    exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    return returnJsonResult(exchange,json.toJSONString());
                }
            return exchange.getResponse().setComplete();
        }else{
            if(!exchange.getRequest().getHeaders().containsKey("Authorization")){
                JSONObject json = new JSONObject();
                json.put("desc","无token值");
                json.put("code","401");
                return returnJsonResult(exchange,json.toJSONString());
            }
            String token = exchange.getRequest().getHeaders().getFirst("Authorization");
            System.out.println("token="+token);
            if (null == token || "".equals(token.trim())) {
                JSONObject json = new JSONObject();
                json.put("desc","未登录");
                json.put("code","401");
                return returnJsonResult(exchange,json.toJSONString());
            }
            System.out.println("token1");
            try{
                System.out.println("token2");
                JwtUtils.checkToken(token);/* 可以正常解析token就放行 财哥 2022/10/31 15:25*/
                System.out.println("token3");
                return  chain.filter(exchange);/* 放行 财哥 2022/10/31 15:25*/
            }catch (Exception ex){
                System.out.println("token4");
                JSONObject json = new JSONObject();
                json.put("desc","token验证失败");
                json.put("code","401");
                return returnJsonResult(exchange,json.toJSONString());
            }
        }
    }

    /**
     * 拦截并返回自定义的json字符串
     */
    private Mono<Void> returnJsonResult(ServerWebExchange exchange, String msg) {
        ServerHttpResponse response = exchange.getResponse();
//        response.setStatusCode(HttpStatus.OK);
        //这里在返回头添加编码,否则中文会乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] bytes = JSON.toJSONBytes(msg, SerializerFeature.WriteMapNullValue);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(buffer));
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

<think>好的,我现在需要帮助用户了解如何将SaToken与Spring Cloud Gateway集成。用户已经提供了相关的引用内容,我需要根据这些信息来构建一个详细的回答,同时遵循之前的格式要求,比如使用中文、正确的LaTeX格式、生成相关问题等等。 首先,我需要回忆一下SaToken的基本功能和集成方式。SaToken是一个轻量级的Java权限认证框架,支持登录认证、权限验证等功能。Spring Cloud Gateway作为API网关,负责请求的路由和过滤,所以集成SaToken需要在网关层进行权限认证和 token 校验。 根据引用[2]中的内容,用户提到了在gateway模块实现功能的步骤,但具体的代码示例可能没有详细给出。因此,我需要结合Spring Cloud Gateway的常见集成方式,比如使用全局过滤器(GlobalFilter)来处理SaToken的认证逻辑。 接下来,我需要确保回答结构清晰,分步骤说明集成配置的过程,包括添加依赖、配置路由和过滤器、实现全局过滤器进行鉴权、处理跨域问题等。同时,要提供示例代码,并注意代码的正确性,比如使用正确的类和方法。 同时,需要遵循用户给出的系统级指令,比如行内数学表达式用$...$,独立公式用$$...$$,但在这个问题中可能涉及数学公式较少,主要关注代码和配置步骤。还要生成相关问题,确保符合用户的要求。 现在,我需要检查是否有遗漏的步骤,比如SaToken的配置是否需要额外的设置,比如Redis集成或者token超时配置。根据用户提供的引用,可能需要在auth模块中实现登录接口和token生成,因此在gateway中主要进行校验和鉴权。 另外,跨域处理在网关层统一配置是比较常见的做法,需要确保CORS配置正确,避免前端请求被拦截。 最后,生成的相关问题需要围绕SaToken和Gateway集成后的性能分析、异常处理、动态权限等,这些都是用户可能进一步关心的点。</think>### SaToken与Spring Cloud Gateway集成配置教程 #### 1. 添加依赖 在`gateway`模块的`pom.xml`中添加SaToken和Spring Cloud Gateway依赖: ```xml <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-reactor-spring-boot-starter</artifactId> <version>1.34.0</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> ``` #### 2. 配置路由与白名单 在`application.yml`中配置路由规则和接口白名单: ```yaml sa-token: # 配置Token名称与有效期 token-name: satoken timeout: 1800 spring: cloud: gateway: routes: - id: auth-service uri: lb://auth-service predicates: - Path=/api/auth/** filters: - StripPrefix=2 # 其他服务路由... ``` #### 3. 实现全局鉴权过滤器 创建`SaTokenGlobalFilter`类处理权限校验: ```java @Component public class SaTokenGlobalFilter implements GlobalFilter { // 白名单列表(可从数据库动态加载) private static final List<String> WHITE_LIST = Arrays.asList("/auth/login", "/public/**"); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getURI().getPath(); // 白名单直接放行 if (checkWhiteList(path)) { return chain.filter(exchange); } // 执行SaToken登录校验 return SaReactorUtil.checkLogin() .setCheckLogin(true) .setAuthFun(r -> { // 添加权限验证逻辑示例 if (!StpUtil.hasPermission("user:read")) { throw new NotPermissionException("user:read"); } }) .run(chain.filter(exchange)); } private boolean checkWhiteList(String path) { return WHITE_LIST.stream().anyMatch(pattern -> new AntPathMatcher().match(pattern, path)); } } ``` #### 4. 跨域配置(可选) 在网关统一配置跨域: ```java @Configuration public class CorsConfig { @Bean public CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); } } ``` #### 5. 最佳实践建议 1. **动态路由管理**:将路由配置存储在Nacos等配置中心实现动态更新 2. **权限缓存优化**:集成Redis实现分布式会话存储: ```yaml sa-token: token-name: satoken timeout: 7200 is-share: true is-read-body: false jwt: secret-key: your-secret-key-here ``` 3. **流量控制**:结合Sentinel实现接口限流保护 4. **日志审计**:在过滤器中添加请求日志记录 [^1]: SaToken官方示例仓库中提供了WebFlux环境下的完整配置参考 [^2]: 认证服务建议采用模块化设计,将鉴权逻辑集中在网关层处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值