增加网关相关注释

This commit is contained in:
liuweijw
2018-08-16 16:40:56 +08:00
parent 4673c96a8d
commit 176c7a6d89
14 changed files with 120 additions and 37 deletions

View File

@@ -8,17 +8,22 @@ import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import com.github.liuweijw.commons.utils.StringHelper;
import com.github.liuweijw.core.commons.constants.ServiceIdConstant;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
/**
* swagger 资源配置
*
* @author liuweijw
*/
@Component
@Primary
public class FwSwaggerResourcesProvider implements SwaggerResourcesProvider {
private final RouteLocator routeLocator;
private final RouteLocator routeLocator;
public FwSwaggerResourcesProvider(RouteLocator routeLocator) {
this.routeLocator = routeLocator;
@@ -31,11 +36,9 @@ public class FwSwaggerResourcesProvider implements SwaggerResourcesProvider {
routes.forEach(route -> {
// swagger排除 auth 模块
if (!StringHelper.contains(route.getId(), ServiceIdConstant.AUTH_SERVICE)) {
resources.add(buildSwaggerResource(route.getId(), route.getFullPath().replace("**",
"v2/api-docs")));
resources.add(buildSwaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs")));
}
});
return resources;
}

View File

@@ -19,40 +19,59 @@ import com.github.liuweijw.system.gateway.filter.ValidateCodeFilter;
import com.github.liuweijw.system.gateway.handler.AccessDeniedHandler;
/**
* 资源权限配置
*
* @author liuweijw
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
/**
* 无需认证的请求URL配置
*/
@Autowired
private FwUrlsConfiguration urlsConfiguration;
/**
* 权限请求认证 Handler
*/
@Autowired
private OAuth2WebSecurityExpressionHandler expressionHandler;
/**
* 访问权限认证 Handler
*/
@Autowired
private AccessDeniedHandler accessDeniedHandler;
/**
* 验证码过滤器
*/
@Autowired
private ValidateCodeFilter validateCodeFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
// 首先进行验证码过滤逻辑
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);
// 允许使用iframe 嵌套避免swagger-ui 不被加载的问题
http.headers().frameOptions().disable();
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
.authorizeRequests();
// 排除无需认证的请求
for (String url : urlsConfiguration.getCollects()) {
registry.antMatchers(url).permitAll();
}
// 通过切面进行验证 { @link PermissionService.hasPermission }
registry.anyRequest().access("@permissionService.hasPermission(request,authentication)");
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
// 认证回调
resources.expressionHandler(expressionHandler);
// 访问异常回到
resources.accessDeniedHandler(accessDeniedHandler);
}
@@ -71,6 +90,11 @@ public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
return expressionHandler;
}
/**
* 密码生成规则
*
* @return 密码生成器
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();

View File

@@ -3,8 +3,6 @@ package com.github.liuweijw.system.gateway.fallback;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -15,8 +13,12 @@ import org.springframework.stereotype.Component;
import com.github.liuweijw.core.commons.constants.MessageConstant;
import com.github.liuweijw.core.commons.constants.ServiceIdConstant;
import lombok.extern.slf4j.Slf4j;
/**
* @author liuweijw Admin 模块异常回调
* Admin 模块异常回调
*
* @author liuweijw
*/
@Slf4j
@Component
@@ -53,8 +55,9 @@ public class AdminFallbackProvider implements FallbackProvider {
return new ByteArrayInputStream(cause.getMessage().getBytes());
} else {
log.error("调用:{} 异常:{}", getRoute(), MessageConstant.BUSINESS_ADMIN_NOTSUPPORT);
return new ByteArrayInputStream(MessageConstant.BUSINESS_ADMIN_NOTSUPPORT
.getBytes());
return new ByteArrayInputStream(
MessageConstant.BUSINESS_ADMIN_NOTSUPPORT
.getBytes());
}
}

View File

@@ -4,8 +4,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -16,8 +14,12 @@ import org.springframework.stereotype.Component;
import com.github.liuweijw.core.commons.constants.MessageConstant;
import com.github.liuweijw.core.commons.constants.ServiceIdConstant;
import lombok.extern.slf4j.Slf4j;
/**
* @author liuweijw Auth 模块异常回调
* Auth 模块异常回调
*
* @author liuweijw
*/
@Slf4j
@Component
@@ -45,8 +47,9 @@ public class AuthFallbackProvider implements FallbackProvider {
return new ByteArrayInputStream(cause.getMessage().getBytes());
} else {
log.error("调用:{} 异常:{}", getRoute(), MessageConstant.SYSTEM_AUTH_NOTSUPPORT);
return new ByteArrayInputStream(MessageConstant.SYSTEM_AUTH_NOTSUPPORT
.getBytes());
return new ByteArrayInputStream(
MessageConstant.SYSTEM_AUTH_NOTSUPPORT
.getBytes());
}
}

View File

@@ -13,7 +13,9 @@ import com.netflix.zuul.context.RequestContext;
import com.xiaoleilu.hutool.collection.CollectionUtil;
/**
* @author liuweijw 在RateLimitPreFilter 之前执行,否则会出现空指针问题
* 在RateLimitPreFilter 之前执行,否则会出现空指针问题
*
* @author liuweijw
*/
@Component
public class AccessFilter extends ZuulFilter {
@@ -38,12 +40,14 @@ public class AccessFilter extends ZuulFilter {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.set("startTime", System.currentTimeMillis());
// 传递 { @link SecurityConstant.ROLE_HEADER } 头部角色权限到下游请求
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null
&& !"anonymousUser".equals(authentication.getPrincipal().toString())) {
ctx.addZuulRequestHeader(SecurityConstant.USER_HEADER, authentication.getName());
ctx.addZuulRequestHeader(SecurityConstant.ROLE_HEADER, CollectionUtil.join(
authentication.getAuthorities(), ","));
ctx.addZuulRequestHeader(
SecurityConstant.ROLE_HEADER, CollectionUtil.join(
authentication.getAuthorities(), ","));
}
return null;
}

View File

@@ -11,13 +11,15 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
/**
* @author liuweijw 网关统一异常处理
* 网关统一异常处理
*
* @author liuweijw
*/
@Component
public class ErrorHandlerFilter extends ZuulFilter {
@Autowired
private LogService logService;
private LogService logService;
@Override
public String filterType() {
@@ -37,6 +39,7 @@ public class ErrorHandlerFilter extends ZuulFilter {
@Override
public Object run() {
// 发送 mq 记录日志
RequestContext requestContext = RequestContext.getCurrentContext();
logService.send(requestContext);
return null;

View File

@@ -11,13 +11,15 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
/**
* @author liuweijw 网关日志拦截器
* 网关日志拦截器
*
* @author liuweijw
*/
@Component
public class LoggerFilter extends ZuulFilter {
@Autowired
private LogService logService;
private LogService logService;
@Override
public String filterType() {
@@ -36,6 +38,7 @@ public class LoggerFilter extends ZuulFilter {
@Override
public Object run() {
// 发送 mq 记录日志
logService.send(RequestContext.getCurrentContext());
return null;
}

View File

@@ -23,18 +23,29 @@ import com.github.liuweijw.core.commons.constants.SecurityConstant;
import com.github.liuweijw.exception.ValidateCodeException;
/**
* @author liuweijw 验证码校验true开启false关闭校验 更细化可以 clientId 进行区分
* 验证码校验true开启false关闭校验 更细化可以 clientId 进行区分
*
* @author liuweijw
*/
@Component("validateCodeFilter")
public class ValidateCodeFilter extends OncePerRequestFilter {
/**
* 根据业务是否需要对验证码进行验证
*/
@Value("${security.validate.code:false}")
private boolean isValidate;
@SuppressWarnings("rawtypes")
/**
* redis 操作工具
*/
@Autowired
@SuppressWarnings("rawtypes")
private RedisTemplate redisTemplate;
/**
* JOSN OBJECT 操作工具
*/
@Autowired
private ObjectMapper objectMapper;

View File

@@ -7,8 +7,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
@@ -21,15 +19,19 @@ import com.github.liuweijw.core.commons.constants.CommonConstant;
import com.github.liuweijw.core.commons.constants.MessageConstant;
import com.github.liuweijw.exception.DeniedException;
import lombok.extern.slf4j.Slf4j;
/**
* @author liuweijw 授权拒绝处理器覆盖默认的OAuth2AccessDeniedHandler 包装失败信息到DeniedException
* 授权拒绝处理器覆盖默认的OAuth2AccessDeniedHandler 包装失败信息到DeniedException
*
* @author liuweijw
*/
@Slf4j
@Component
public class AccessDeniedHandler extends OAuth2AccessDeniedHandler {
@Autowired
private ObjectMapper objectMapper;
private ObjectMapper objectMapper;
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
@@ -37,8 +39,9 @@ public class AccessDeniedHandler extends OAuth2AccessDeniedHandler {
log.info("授权失败,禁止访问 {}", request.getRequestURI());
response.setCharacterEncoding(CommonConstant.UTF8);
response.setContentType(CommonConstant.CONTENT_TYPE);
R<String> result = new R<String>().failure(new DeniedException(
MessageConstant.COMMONS_AUTH_NOTSUPPORT));
R<String> result = new R<String>().failure(
new DeniedException(
MessageConstant.COMMONS_AUTH_NOTSUPPORT));
response.setStatus(HttpStatus.SC_FORBIDDEN);
PrintWriter printWriter = response.getWriter();
printWriter.append(objectMapper.writeValueAsString(result));

View File

@@ -1,13 +1,13 @@
package com.github.liuweijw.system.gateway.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.DefaultRateLimiterErrorHandler;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.RateLimiterErrorHandler;
import lombok.extern.slf4j.Slf4j;
/**
* 限流降级处理
*

View File

@@ -2,6 +2,11 @@ package com.github.liuweijw.system.gateway.service;
import com.netflix.zuul.context.RequestContext;
/**
* 往消息通道发消息
*
* @author liuweijw
*/
public interface LogService {
/**

View File

@@ -25,11 +25,16 @@ import com.xiaoleilu.hutool.http.HttpUtil;
import com.xiaoleilu.hutool.io.IoUtil;
import com.xiaoleilu.hutool.util.URLUtil;
/**
* 日志异步实现
*
* @author liuweijw
*/
@Component
public class LogServiceImpl implements LogService {
@Autowired
private AmqpTemplate rabbitTemplate;
private AmqpTemplate rabbitTemplate;
@Override
public void send(RequestContext requestContext) {

View File

@@ -4,6 +4,11 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
/**
* 权限接口
*
* @author liuweijw
*/
public interface PermissionService {
/**

View File

@@ -6,8 +6,6 @@ import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.core.Authentication;
@@ -24,13 +22,26 @@ import com.github.liuweijw.core.commons.jwt.JwtUtil;
import com.github.liuweijw.system.api.PermissionFeignApi;
import com.github.liuweijw.system.api.model.AuthPermission;
import lombok.extern.slf4j.Slf4j;
/**
* 权限接口实现
*
* @author liuweijw
*/
@Slf4j
@Service("permissionService")
public class PermissionServiceImpl implements PermissionService {
/**
* 具体Admin工程实现
*/
@Autowired
private PermissionFeignApi permissionFeignApi;
/**
* redis 工厂类
*/
@Autowired
private RedisConnectionFactory redisConnectionFactory;