springcloud整合nacos、sentinal、springcloud-gateway,springboot security、oauth2总结

源码地址:下载地址

使用该架构的项目地址:下载地址

下面教大家整合nacos、sentinal、springcloud-gateway,springboot security、oauth2做一个分布式架构

1、第一步整合nacos

1、下载alibaba的nacos 下载地址,然后使用单机模式启动nacos

sh startup.sh -m standalone

启动之后登录 http://localhost:8848/nacos/#/login ,账号密码都是默认的nacos。

2、第二步建立业务项目结构


项目结构图片

3、第三步建立项目的入口(网关服务)

首先入口接口网关模块

pom文件

  <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.xyw.code</groupId>
        <artifactId>xptx-gateway</artifactId>
        <version>1.0.0</version>
    </parent>
    <groupId>com.xyw.code</groupId>
    <artifactId>xptx-spring-gateway</artifactId>
    <version>1.0.0</version>
    <name>xptx-spring-cloud-gateway</name>
    <description>spring-cloud-gateway网关服务</description>

    <properties>
        <java.version>1.8</java.version>
        <swagger2.version>2.8.0</swagger2.version>
        <xptx.version>1.0.0</xptx.version>
        <spring-boot.version>2.1.8.RELEASE</spring-boot.version>
    </properties>


    <dependencies>
        <!--nacos注册中心客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos配置中心客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--gateway 网关依赖,内置webflux 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger2.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger2.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyw.code</groupId>
            <artifactId>xptx-common-core</artifactId>
            <version>${xptx.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyw.code</groupId>
            <artifactId>xptx-common-redis</artifactId>
            <version>${xptx.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyw.code</groupId>
            <artifactId>xptx-auth-client</artifactId>
            <version>${xptx.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>javax.servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

<font color=red>

集成网关的时候有个坑注意下,因为网关自带web,所以集成网关的时候不能携带任何api或者web的模块,不会启动会报错

</font>


设置好入口之后修改下application.yml文件设置下网关服务的入口和业务服务的入口

  routes:
    #        基础服务
    - id: xptx-system-base-server
      # lb代表从注册中心获取服务,且已负载均衡方式转发
      uri: lb://xptx-system-base-server
      predicates: # 路由条件,Predicate 接受一个输入参数,返回一个布尔值结果
        - Path=/sys/**
      filters:
        - SwaggerHeaderFilter
        - StripPrefix=1
        # 降级配置
        - name: Hystrix
          args:
            name: fallback
            fallbackUri: forward:/fallback
    #        授权服务
    - id: xptx-auth
      uri: http://localhost:8001
      predicates:
        - Path=/auth/**
      filters:
        - ImageCodeFilter
        - RemoveRequestHeader=Origin
        - StripPrefix=1
        # 降级配置
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/fallback

然后有一点要注意的

网关和业务数据可以通过两种方式鉴权

1、服务器鉴权

首先业务数据集成xptx-common-auth模块拿到鉴权注解。之后的鉴权可以通过@PreAuthorize来实现。

例子

/**
     * 根据id删除菜单
     *
     * @param id
     * @return
     */
    @ApiOperation("删除菜单")
    @PreAuthorize("hasAuthority('sys:menu:delete')")
    @SysOperateLog(descrption = "删除菜单")
    @DeleteMapping("/{id}")
    public R deleteMenu(@PathVariable("id") Integer id) {
        return menuService.removeMenuById(id);
    }
2、网关那里鉴权

在网关那里实现一个全局拦截器去鉴权

package com.prex.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * 调用鉴权
 */
@Slf4j
@Component
public class AuthSignatureFilter implements GlobalFilter, Ordered {

    // 排除过滤的 uri 地址
    private static final String[] WHITE_LIST = {"/*/v2/api-docs", "/user/register", "/swagger-ui.html",
            "/swagger-resources/**",
            "/*/api-docs",
            "/api/socket/**",
            "/log"};

    private AntPathMatcher antPathMatcher = new AntPathMatcher();


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        String uriPath = request.getPath().toString();

        log.info("url:{}", uriPath);
        boolean action = false;
        for (String url : WHITE_LIST) {
            if (antPathMatcher.match(url, uriPath)) {
                action = true;
                break;
            }
        }
        // 跳过不需要验证的路径
        if (action) {
            return chain.filter(exchange);
        }

        String token = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (null == token || token.isEmpty()) {
            ServerHttpResponse response = exchange.getResponse();
            //当请求不携带Token或者token为空时,直接设置请求状态码为401,返回
            InetSocketAddress remoteAddress = request.getRemoteAddress();
            String clientIp = Objects.requireNonNull(remoteAddress).getAddress().getHostAddress();
            log.info("非法请求,客户端IP:" + clientIp + "URL:" + request.getPath());
            JSONObject message = new JSONObject();
            message.put("code", HttpStatus.UNAUTHORIZED.value());
            message.put("msg", "非法请求");
            byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //指定编码,否则在浏览器中会中文乱码
            response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));

        }
        ServerHttpRequest authorization = request.mutate().headers(httpHeaders -> {
            httpHeaders.add("Authorization", token);
        }).build();
        ServerWebExchange serverWebExchange = exchange.mutate().request(authorization).build();
        return chain.filter(serverWebExchange);
    }

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

全局拦截器调用的是鉴权客户端,然后鉴权客户端可以通过feign去调用鉴权服务端来判断用户是否拥有这个权限。这就是大致简单的整合流程。

4、第三步建立项目的认证服务

认证服务分为两部分:

1:

一部分把认证服务作为一个jar包,目的是作为一个认证客户端给第三方引用(<font color='red'>这里有个坑,千万不能加入<artifactId>spring-boot-maven-plugin</artifactId>这个插件,因为这个插件会导致maven多moudle依赖找不到引入jar包依赖</font>)。

2:

就是一个鉴权服务,里面整合了spring-security和spring-oauth2。这两个大致作用是spring-security用来存储用户,通过用户鉴权来获取token。但是有些时候第三方服务想调用我们的接口,那我们为了不提供自己的账号密码给别人,因此就使用了oauth2,通过提供client_id和serect的方式来获取token,从而来被允许调用我们的服务。

获取token的链接:http://localhost:8002/auth/oauth/token?username=admin&password=admin&t=1571628400280&code=fzbz&grant_type=password&scope=server

总结

分布式项目整合一切以网关为入口,然后网关前缀分为业务项目的前缀和认证服务器前缀。最后网关还会有一个全局拦截器去拦截认证请求
© 著作权归作者所有,转载或内容合作请联系作者

喜欢的朋友记得点赞、收藏、关注哦!!!

相关推荐
bjzhang751 小时前
SpringBoot开发——集成Tess4j实现OCR图像文字识别
spring boot·ocr·tess4j
flying jiang1 小时前
Spring Boot 入门面试五道题
spring boot
小菜yh1 小时前
关于Redis
java·数据库·spring boot·redis·spring·缓存
爱上语文3 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
serve the people3 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
罗政8 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
拾光师9 小时前
spring获取当前request
java·后端·spring
xujinwei_gingko10 小时前
Spring IOC容器Bean对象管理-Java Config方式
java·spring
天高任鸟飞dyz11 小时前
html加载页面
css·html·css3