基于spring.cloud使用zuul实现路由的简单方式

最近项目中需要对某些接口判断是否登录状态,简单说就是权限验证,之前的项目中用的是spring security,但由于本项目用的是spring cloud所以就想到了zuul,期间也遇到了些小问题,也到网上找了资料,自己做个笔记,有不对的地方请看到的大牛们不要太过介意,也希望可以对对指正,谢谢

zuul就是对我们的服务被访问之前做个路由,实际可以看成一个网关~

首先加入pom依赖:

在这里插入图片描述
application.properties文件配置:

zuul.routes.serviceName.path=/ai/** //配置好以后,在访问路径前加/ai,这样就进入到我们的网关管理了
zuul.routes.serviceName.url=http://127.0.0.1:8998/ //ip,应用端口
management.security.enabled=false //微服务不从其他的权限管理

zuul.host.socket-timeout-millis=60000
zuul.host.connect-timeout-millis=10000 //timeout 时间,有兴趣可以到官网自己看看

编写相应filtter://要extends ZuulFilter

public class AccessFilter extends ZuulFilter {

private static final Logger logger = LogManager.getLogger(AccessFilter.class);

@Value("${ignoreUrl}")
private String ignoreUrl;

@Autowired
private UserService userService;

@Override
public String filterType() {
    return "pre";
}

@Override
public int filterOrder() {
    return 0;
}

@Override
public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();

    HttpServletResponse response = ctx.getResponse();
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json");

    String requestUri = request.getRequestURI();
    String ip = getIp(request);
    String _applicationId = request.getHeader(Constants.HEADER_APPLICATION_ID);
    if (StringUtils.isEmpty(_applicationId)) {
        ctx.setResponseBody("应用编号不能为空");
        logger.error("applicationId is empty,{},ip,{}", requestUri, ip);
        BizException.isNull(_applicationId, "应用编号");
    }

    String _applicationClientType = request.getHeader(Constants.HEADER_APPLICATION_CLIENT_TYPE);
    if (StringUtils.isEmpty(_applicationClientType)) {
        ctx.setResponseBody("客户端类型不能为空");
        logger.error("applicationClientType is empty,ip,{}", requestUri, ip);
        BizException.isNull(_applicationClientType, "客户端类型");
    }

    Long applicationId = Long.parseLong(_applicationId);
    Integer applicationClientType = Integer.parseInt(_applicationClientType);

    ApplicationClientTypeEnum applicationClientTypeEnum = ApplicationClientTypeEnum.getInstance(applicationClientType);
    String token = request.getHeader(Constants.HEADER_TOKEN);

    //判断是否为登录接口
    if (requestUri.indexOf("login") > 0) {
        return ctx;
    }

    //获取不需要验证的url
    List<String> ignoreList = analysisIgnoreUrl();

    if ((requestUri.startsWith("/ai") && !ignoreList.contains(requestUri))) {
        if (StringUtils.isEmpty(token)) {
            ctx.setResponseBody("token不能为空");
            BizException.fail(ApiResponseCode.NOT_LOG, "token为空,未登录");
        }
        UserInfoVO user = userService.validateToken(token, applicationId, applicationClientTypeEnum);

            if (!Objects.isNull(user)) {

// HttpServletRequestWrapper wrappedRequest = modifyRequest(request, user);
ctx.addZuulRequestHeader(Constants .REQUEST_HEADER_USER_ID, user.getUserId().toString());
// ctx.addZuulRequestHeader(com.yztz.common.constant.Constants.REQUEST_HEADER_USER_NAME, user.getUserName());
// ctx.setRequest(wrappedRequest);
return ctx;
} else {
ctx.setResponseBody(“token错误”);
BizException.fail(ApiResponseCode.NOT_LOG, “token错误”);
}

    } else {
        return ctx;
    }
    return null;
}

@Override
public boolean shouldFilter() {
    return true;
}

代码里我做了请求设备类型及id的一些判断,还编写了一个不需要走token验证的接口的配置
在properties里面配置,如登录接口
ignoreUrl=/ai/login

启动入口加入相应注解:

@ServletComponentScan
@SpringBootApplication
@EnableZuulProxy
public class Application {

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}
//实例化过滤器
@Bean
@RefreshScope
public AccessFilter accessFilter() {
    return new AccessFilter();
}

}

到此就应该可以使用zuul进行路由微服务了,但是注意在uri前面加上/ai哦…

开发过程中还有个前端人员需要跨域请求的问题,在这里也一并说一下,做个记录
在一开始的时候在外面做了处理如
@Component
@Configuration
public class CrosInterceptor {

/**
* attention:简单跨域就是GET,HEAD和POST请求,但是POST请求的"Content-Type"只能是application/x-www-form-urlencoded, multipart/form-data 或 text/plain
* 反之,就是非简单跨域,此跨域有一个预检机制,说直白点,就是会发两次请求,一次OPTIONS请求,一次真正的请求
*/

@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);// 允许cookies跨域
corsConfiguration.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
corsConfiguration.addAllowedOrigin("");// #允许向该服务器提交请求的URI,表示全部允许,在SpringMVC中,如果设成,会自动转成当前请求头中的Origin
corsConfiguration.addAllowedHeader("
");// #允许访问的头信息,*表示全部
corsConfiguration.addAllowedMethod(“GET”);
corsConfiguration.addAllowedMethod(“POST”);
corsConfiguration.addAllowedMethod(“DELETE”);
corsConfiguration.addAllowedMethod(“PUT”);

urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
    /*FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(urlBasedCorsConfigurationSource));
    // 这个顺序很重要哦,为避免麻烦请设置在最前
    bean.setOrder(0);*/
return new CorsFilter(urlBasedCorsConfigurationSource);

}

}
但是发现一旦加上/ai就是试图路由我的请求就会有跨域的问题,原因是我们只是在外面做了跨域处理,但是微服务间并没有所以要加入

@Component
public class CorsFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
   /* String curOrigin = request.getHeader("Origin");
    System.out.println("###跨域过滤器->当前访问来源->"+curOrigin+"###");   */
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "*");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    chain.doFilter(request, response);

}

@Override
public void destroy() {

}

}

properties里面加入
zuul.sensitiveHeaders= Access-Control-Allow-Origin
zuul.ignoredHeaders= Access-Control-Allow-Origin,H-APP-Id,APPToken

到此就完美解决了跨域的问题了。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值