SpringCloud 微服务安全实战 Zuul网关安全
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了SpringCloud 微服务安全实战 Zuul网关安全,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6782字,纯文字阅读大概需要10分钟。
内容图文
微服务架构下的问题:
安全处理和业务逻辑耦合,增加了复杂性和变更成本
随着业务节点增加,认证服务器压力增大
多个微服务同时暴露,增加了外部访问的复杂性
网关解决方案:
网关服务代码:
POM.xml:
<!-- zuul网关相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<!-- end -->
<!-- 限流相关 -->
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<!-- end -->
限流配置,网关配置:
qpplicatoin.yml:
zuul:
routes:
token:
url: http://localhost:9090
order:
url: http://localhost:9080
# 敏感头 设置为空,所有请求都往后转发
sensitive-headers:
# 限流配置
ratelimit:
enabled: true
repository: JPA #REDIS
default-policy-list: #默认限流策略
- limit: 2 #请求数
quota: 2 #加在一起请求的时间
refresh-interval: 1 #1秒钟之内可以有几个请求
type: #根据什么来处理流量
- url /a get
- httpmethod
policy-list: #根据路由规则限流
token:
- limit: 2
quota: 2
refresh-interval: 1
type:
spring:
qpplication:
name: gateway
datasource:
url: jdbc:mysql://localhost:3306/imooc-security?characterEncoding=utf-8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
jpa:
generate-ddl: true
show-sql: true
server:
port: 9070
启动类:
/**
* @author aric
* @create 2021-04-07-17:59
* @fun
*/
@SpringBootApplication
@EnableZuulProxy
public class GatewayServer {
public static void main(String[] args) {
SpringApplication.run(GatewayServer.class,args);
}
}
Token信息:
/**
* @author aric
* @create 2021-04-07-18:22
* @fun
*/
@Data
public class TokenInfo {
private boolean active;
private String client_id;
private String[] scope;
private String user_name;
//权限数组
private String[] aud;
//过期时间
private Date exp;
//用户所有的权限
private String[] authorities;
}
三个(认证,日志,授权)网关配置:
认证code:
/**
* @author aric
* @create 2021-04-07-18:07
* @fun
*/
@Component
@Slf4j
public class OAuthFilter extends ZuulFilter {
private RestTemplate restTemplate = new RestTemplate();
//是否过滤
@Override
public boolean shouldFilter(){
return true;
}
//业务逻辑
@Override
public Object run(){
log.info("oauth start");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if(StringUtils.startsWith(request.getRequestURI(),"/token")){
//发往认证服务器的请求不需要认证
return null;
}
//别的请求
String authHeader = request.getHeader("Authorization");
//没带请求头
if(StringUtils.isBlank(authHeader)){
return null;
}
//不是bearer开头的不用处理
if(!StringUtils.startsWithIgnoreCase(authHeader,"bearer ")){
return null;
}
try{
TokenInfo info = getTokenInfo(authHeader);
request.setAttribute("tokenInfo",info);
} catch (Exception e){
log.error("get token info fail",e);
}
return null;
}
private TokenInfo getTokenInfo(String authHeader) {
//去掉头部信息,拿到token
String token = StringUtils.substringAfter(authHeader,"bearer ");
String oauthServiceUrl = "http://localhost:9090/oauth/check_token";
//发请求
HttpHeaders headers = new HttpHeaders();
//规定发送的是表单
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//设置请求头BasicAuth信息
headers.setBasicAuth("gateway","123465");
//请求参数设置
MultiValueMap<String,String> params = new LinkedMultiValueMap<String, String>();
params.add("token",token);
//设置返回实体
HttpEntity<MultiValueMap<String,String>> entity = new HttpEntity<MultiValueMap<String,String>>(params,headers);
ResponseEntity<TokenInfo> response = restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity,TokenInfo.class);
log.info("token info :" + response.getBody().toString());
return response.getBody();
}
//过滤器类型,在之前or 之后 or 错误 or rout 时执行run方法
@Override
public String filterType(){
return "pre";
}
//控制过滤器的执行顺序
@Override
public int filterOrder(){
return 1;
}
}
日志code:
/**
* @author aric
* @create 2021-04-07-18:39
* @fun
*/
@Component
@Slf4j
public class AuditLogFilter extends ZuulFilter {
@Override
public boolean shouldFilter(){
return true;
}
@Override
public Object run(){
log.info("audit log insert");
return null;
}
@Override
public String filterType(){
return "pre";
}
@Override
public int filterOrder() {
return 2;
}
}
授权code:
/**
* @author aric
* @create 2021-04-07-18:43
* @fun
*/
@Component
@Slf4j
public class AuthorizationFilter extends ZuulFilter {
@Override
public boolean shouldFilter(){
return true;
}
@Override
public Object run(){
log.info("authorization start");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//判断当前请求需要认证否?
if(isNeedAuth(request)){
TokenInfo tokenInfo = (TokenInfo)request.getAttribute("tokenInfo");
if(tokenInfo != null && tokenInfo.isActive()){
//拿到用户信息,判断是否有权限
if(!hasPermission(tokenInfo,request)){
log.info("audit log update fail 403");
handlerError(403,requestContext);
}
requestContext.addZuulRequestHeader("username",tokenInfo.getUser_name());
}else{
//拿不到认证信息
if(!StringUtils.startsWith(request.getRequestURI(),"/token")) {
log.info("audit log update fail 401");
handlerError(401, requestContext);
}
}
}
return null;
}
private boolean hasPermission(TokenInfo tokenInfo, HttpServletRequest request) {
//随机50%成功
return RandomUtils.nextInt()%2 == 0;
}
private void handlerError(int status, RequestContext requestContext) {
requestContext.getResponse().setContentType("application/json");
requestContext.setResponseStatusCode(status);
requestContext.setResponseBody("{\"message\":\"auth fail\"}");
requestContext.setSendZuulResponse(false);
}
private boolean isNeedAuth(HttpServletRequest request) {
return true;
}
@Override
public String filterType(){
return "pre";
}
@Override
public int filterOrder() {
return 3;
}
}
扩展:
自定义限流处理规则:
/**
* @author aric
* @create 2021-04-07-21:04
* @fun 自定义限流规则
*/
@Component
public class MyKeyGen extends DefaultRateLimitKeyGenerator {
public MyKeyGen(RateLimitProperties properties, RateLimitUtils rateLimitUtils) {
super(properties, rateLimitUtils);
}
@Override
public String key(HttpServletRequest request, Route route, RateLimitProperties.Policy policy){
//在这里实现自己的限流规则
return super.key(request,route,policy);
}
}
异常记录:
/**
* @author aric
* @create 2021-04-07-21:08
* @fun 异常记录
*/
@Slf4j
public class MyRateLimitHandler extends DefaultRateLimiterErrorHandler {
//往存储里存的时候的异常
@Override
public void handleSaveError(String key, Exception e) {
log.error("Failed saving rate for " + key + ", returning unsaved rate", e);
}
@Override
//往存储里取的时候的异常
public void handleFetchError(String key, Exception e) {
log.error("Failed retrieving rate for " + key + ", will create new rate", e);
}
@Override
//限流过程中发生错误异常处理
public void handleError(String msg, Exception e) {
log.error(msg, e);
}
}
内容总结
以上是互联网集市为您收集整理的SpringCloud 微服务安全实战 Zuul网关安全全部内容,希望文章能够帮你解决SpringCloud 微服务安全实战 Zuul网关安全所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。