在上一章博客中,写了如何生成token,现在我们来讲一下如何实现登录拦截功能,意思就是必须使用用户名和密码登录之后,才能调用其他接口,这是项目的基础功能之一。现在我们来看一下代码。
(1)因为项目是springcloud项目,所以一切的请求都会先经过网关,然后再通过负载均衡,分发到相应的微服务上。所以我们的拦截就是是网关处实现。主要思想就是在网关处写一个网关过滤器。判断是否传送过来的请求是否携带token,并且这个token能否被解析成用户信息。如果能,则放行,反之拦截。
代码如下(主要体现思想,代码并不完整):
package com.tao.gateway.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.tao.common.config.RsaProper;
import com.tao.common.pojo.UserInfo;
import com.tao.common.utils.CookieUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
/**
* 网关过滤,判断是否存在对应的token,不存在则返回
*/
public class LoginFilter extends ZuulFilter {
@Autowired
private RsaProper rsaProper;
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 5;
}
@Override
public boolean shouldFilter() {
//获得当前请求环境
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
Cookie[] cookies = request.getCookies();
if (null == cookies || cookies.length < 1) {
return false;
}
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals(rsaProper.getCookieName())) {
return true;
}
}
return false;
}
@Override
public Object run() throws ZuulException {
//如果有token,则把token解析出来
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
HttpServletResponse response = currentContext.getResponse();
UserInfo userInfo = null;
try {
userInfo = CookieUtils.getUserInfoFromCookie(request, response,"TAO_TOKEN");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
if (userInfo == null) {
//没有权限
response.setStatus(203);
}
return null;
}
}
当然,这个网关过滤器还存在一定的缺陷,因为这样的话,在访问登录接口的时候也会被拦截掉。所以我们需要设置一个白名单,白名单里卖弄包含的全部是不需要拦截的接口。这里我就不写上去了,大家可以自行百度,比较简单。
(2)在项目中,不可避免的一个问题就是宽域请求。域名不同、ip不同、端口不同。都算是宽域问题。所以在网关处也要把宽域问题给解决掉。大家可以自行百度看一下cors,cors是一个规范。代码如下:
package com.tao.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 使用cors,解决跨域问题
*/
@Configuration
public class GlobalCorsFilter {
/**
* 把corsFilter注入spring容器中,而且这是一个配置类
* @return
*/
@Bean
public CorsFilter corscorsFilter() {
//生成配置类
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("http://127.0.0.1:10021");
corsConfiguration.addAllowedOrigin("http://127.0.0.1:10020");
corsConfiguration.addAllowedOrigin("http://127.0.0.1:10022");
corsConfiguration.addAllowedOrigin("http://www.schooltao.com");
corsConfiguration.addAllowedOrigin("http://www.taomanage.com");
corsConfiguration.addAllowedOrigin("http://localhost:8080/druid/login.html");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod(HttpMethod.POST);
corsConfiguration.addAllowedMethod(HttpMethod.PUT);
corsConfiguration.addAllowedMethod(HttpMethod.GET);
corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
这样的话就可以解决宽域问题了,当前前端页需要配置以下才行。里面宽域的地址根据自己的需求来更改。
总结:今天内容不难,不过掌握了登录拦截的实现。以前写练习项目的时候,一直没有实现过。还有及时宽域问题。今天的两个内容都是重点,工作中也hi经常遇到。有什么疑问的,可以随时联系我。