认证服务对接网关
新建网关工程changgou_gateway_web
1) changgou_gateway添加依赖
<!--网关依赖--> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> <version>2.1.3.RELEASE</version> </dependency> </dependencies>
2) 新建工程changgou_gateway_web,并创建启动类
@SpringBootApplication @EnableDiscoveryClient public class WebGateWayApplication { public static void main(String[] args) { SpringApplication.run(WebGateWayApplication.class,args); } }
3) 创建application.yml
spring: application: name: gateway-web cloud: gateway: globalcors: cors-configurations: '[/**]': # 匹配所有请求 allowedOrigins: "*" #跨域处理 允许所有的域 allowedMethods: # 支持的方法 - GET - POST - PUT - DELETE routes: - id: changgou_goods_route uri: lb://goods predicates: - Path=/api/album/**,/api/brand/**,/api/cache/**,/api/categoryBrand/**,/api/category/**,/api/para/**,/api/pref/**,/api/sku/**,/api/spec/**,/api/spu/**,/api/stockBack/**,/api/template/** filters: #- PrefixPath=/brand - StripPrefix=1 #用户微服务 - id: changgou_user_route uri: lb://user predicates: - Path=/api/user/**,/api/address/**,/api/areas/**,/api/cities/**,/api/provinces/** filters: - StripPrefix=1 #认证微服务 - id: changgou_oauth_user uri: lb://user-auth predicates: - Path=/api/oauth/** filters: - StripPrefix=1 redis: host: 192.168.200.128 server: port: 8001 eureka: client: service-url: defaultZone: http://127.0.0.1:6868/eureka instance: prefer-ip-address: true management: endpoint: gateway: enabled: true web: exposure: include: true
网关全局过滤器
新建过滤器类AuthorizeFilter,对请求进行过滤
业务逻辑:
1)判断当前请求是否为登录请求,是的话,则放行
2) 判断cookie中是否存在信息, 没有的话,拒绝访问
3)判断redis中令牌是否存在,没有的话,拒绝访问
@Component public class AuthFilter implements GlobalFilter, Ordered { public static final String Authorization = "Authorization"; @Autowired private AuthService authService; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //获取当前请求对象 ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); String path = request.getURI().getPath(); if ("/api/oauth/login".equals(path)){ //放行 return chain.filter(exchange); } //判断cookie上是否存在jti String jti = authService.getJtiFromCookie(request); if (StringUtils.isEmpty(jti)){ //拒绝访问,请求跳转 response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } //判断redis中token是否存在 String redisToken = authService.getTokenFromRedis(jti); if (StringUtils.isEmpty(redisToken)){ //拒绝访问,请求跳转 response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } //校验通过 , 请求头增强,放行 request.mutate().header(Authorization,"Bearer "+redisToken); return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
新建业务逻辑类AuthService
@Service public class AuthService { @Autowired private StringRedisTemplate stringRedisTemplate; /** * 判断cookie中jti是否存在 * @param request * @return */ public String getJtiFromCookie(ServerHttpRequest request) { HttpCookie cookie = request.getCookies().getFirst("uid"); if (cookie!=null){ return cookie.getValue(); } return null; } /** * 判断redis中令牌是否过期 * @param jti * @return */ public String getTokenFromRedis(String jti) { String token = stringRedisTemplate.boundValueOps(jti).get(); return token; } }
测试:
清除postman中的cookie数据,在未登录的情况下,并访问: http://localhost:8001/api/user 。会返回401异常信息
访问:http://localhost:8001/api/oauth/login,并重新测试。可以发现测试通过,拿到返回结果数据
自定义登录页面
认证服务添加依赖
<!--thymeleaf--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
资源\成品页面\登录页面
把页面放到下面的项目中
静态资源放行
修改WebSecurityConfig类
web.ignoring().antMatchers( "/oauth/login", "/oauth/logout","/oauth/toLogin","/login.html","/css/**","/data/**","/fonts/**","/img/**","/js/**");
添加开启表单登录
LoginRedirectController
@Controller @RequestMapping("/oauth") public class LoginRedirectController { @RequestMapping("/toLogin") public String toLogin(){ return "login"; } }
修改登录页面实现用户登录
定义login方法
<script th:inline="javascript"> var app = new Vue({ el:"#app", data:{ username:"", password:"", msg:"" }, methods:{ login:function(){ app.msg="正在登录"; axios.post("/api/oauth/login?username="+app.username+"&password="+app.password).then(function (response) { if (response.data.flag){ app.msg="登录成功"; }else{ app.msg="登录失败"; } }) } } }) </script>
定义路径过滤
public class URLFilter { public static String filterPath = "/api/wseckillorder,/api/seckill,/api/wxpay,/api/wxpay/**,/api/worder/**,/api/user/**,/api/address/**,/api/wcart/**,/api/cart/**,/api/categoryReport/**,/api/orderConfig/**,/api/order/**,/api/orderItem/**,/api/orderLog/**,/api/preferential/**,/api/returnCause/**,/api/returnOrder/**,/api/returnOrderItem/**"; public static boolean hasAuthorize(String url){ String[] split = filterPath.replace("**", "").split(","); for (String value : split) { if (url.startsWith(value)){ return true; } } return false; } }
测试
访问:http://localhost:9200/oauth/toLogin