17、用户认证 Zuul

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 用户中心负责用户管理,包括:用户信息管理、角色管理、权限管理等

用户认证 Zuul

流程:

搭建环境

用户中心负责用户管理,包括:用户信息管理、角色管理、权限管理等

1、创建xc_user数据库(MySQL)

2、创建用户中心工程:xc-service-ucenter

3、查询用户接口

完成用户中心根据账号查询用户信息接口功能

API

在UcenterControllerApi接口中定义getUserext方法

DAO

在XcUserRepository接口中定义findXcUserByUsername方法

在XcCompanyUserRepository接口中定义findByUserId方法

Service

在UserService类中定义findXcUserByUsername、getUserExt方法

Controller

在UcenterController类中定义getUserext方法

测试:

打开浏览器输入:http://localhost:40300/swagger-ui.html

点击:

输入用户名:itcast,查询结果如下:


调用查询用户接口

1、创建client

认证服务需要远程调用用户中心服务查询用户,在认证服务xc-service-ucenter-auth中创建Feign客户端

在UserClient接口中定义getUserext方法

2、UserDetailsServiceImpl

认证服务调用spring security接口申请令牌,spring security接口会调用UserDetailsServiceImpl从数据库查询用 户,如果查询不到则返回 NULL,表示不存在;在UserDetailsServiceImpl中将正确的密码返回, spring security 会自动去比对输入密码的正确性

1、修改UserDetailsServiceImpl的loadUserByUsername方法,调用Ucenter服务的查询用户接口

2、测试,请求:http://localhost:40400/auth/userlogin

观察UserDetailsServiceImpl是否正常请求Ucenter的查询用户接口。


3、BCryptPasswordEncoder

早期使用md5对密码进行编码,每次算出的md5值都一样,这样非常不安全,Spring Security推荐使用 BCryptPasswordEncoder对密码加随机盐,每次的Hash值都不一样,安全性高

1、调用TestClient类中的testPasswrodEncoder测试方法

2、在AuthorizationServerConfig配置类中配置BCryptPasswordEncoder

3、测试请求:http://localhost:40400/auth/userlogin,输入正常的账号和密码进行测试

测试结果:


解析申请令牌错误信息

当账号输入错误应该返回用户不存在的信息,当密码错误要返回用户名或密码错误信息,业务流程图如下:

修改申请令牌的程序解析返回的错误:

由于restTemplate收到400或401的错误会抛出异常,而spring security针对账号不存在及密码错误会返回400及 401,所以在代码中控制针对400或401的响应不要抛出异常

用户不存在:

密码错误:

4、测试使用postman请求:http://localhost:40400/auth/userlogin

1、输入正确的账号和密码进行测试

从数据库找到测试账号,本课程所提供的用户信息初始密码统一为111111

2、输入错误的账号和密码进行测试


JWT查询接口

认证服务对外提供JWT查询接口,流程如下:

1、客户端携带cookie中的身份令牌请求认证服务获取JWT

2、认证服务根据身份令牌从redis中查询jwt令牌并返回给客户端

API

在AuthControllerApi接口中添加userjwt方法;

Service

在AuthService类中添加getUserToken方法;

Controller

在AuthController类中添加userjwt方法;

测试

使用postman测试

1、请求:http://ucenter.xuecheng.com/openapi/auth/userlogin

观察cookie是否已存入用户身份令牌。

2、get:http://ucenter.xuecheng.com/openapi/auth/userjwt

Nginx中配置代理转发

上边实现在首页显示当前用户信息,首页需要通过Nginx代理请求认证服务,所以需要在首页的虚拟主机上配置代 理路径:

#认证
location ^~ /openapi/auth/ { 
  proxy_pass http://auth_server_pool/auth/;
}

注意:其它前端系统要接入认证要请求认证服务也需要配置上边的代理路径。


用户退出

用户退出要有以下动作:

1、删除redis中的token

2、删除cookie中的token

1、API

添加logout方法;

2、Service

添加delToken方法;

3、Controller

添加logout和clearCookie方法;

4、退出URL放行

认证服务默认都要校验用户的身份信息,这里需要将退出url放行。

在WebSecurityConfig类中重写 configure(WebSecurity web)方法,如下:

@Override
 public void configure(WebSecurity web) throws Exception {
     web.ignoring().antMatchers("/userlogin","/userlogout","/userjwt");
 }

测试:点击退出查看效果

POST:http://ucenter.xuecheng.com/openapi/auth/userlogout


Zuul网关

网关的作用相当于一个过滤器、拦截器,它可以拦截多个系统的请求。

Spring Cloud Zuul是整合Netflix公司的Zuul开源项目实现的微服务网关,它实现了请求路由、负载均衡、校验过滤等功能。

官方:https://github.com/Netflix/zuul


服务网关是在微服务前边设置一道屏障,请求先到服务网关,网关会对请求进行过滤、校验、路由等处理。有了服务网关可以提高微服务的安全性和网关校验请求的合法性,当请求不合法时将被拦截,拒绝访问

Zuul与Nginx怎么配合使用?

Zuul与Nginx在实际项目中需要配合使用,如下图,Nginx的作用是反向代理、负载均衡,Zuul的作用是保障微服务的安全访问,拦截微服务请求,校验合法性及负载均衡。

客户发送请求,首先通过Nginx进行请求分发到各个微服务,其中zuul在其中先进行拦截。

Zuul网关具有代理的功能,根据请求的url转发到微服务,如下图:

客户端请求网关/api/learning,通过路由转发到/learning

客户端请求网关/api/course,通过路由转发到/course


搭建网关工程

1、创建xc-govern-gateway工程

2、启动类上添加@EnableZuulProxy注解

3、yml文件中添加以下内容

zuul:
  routes:
    manage-course:
      path: /course/**
      serviceId: xc-service-manage-course #微服务名称,网关会从eureka中获取该服务名称下的服务实例的地址
      # 例子:将请求转发到http://localhost:31200/course
      #url: http://www.baidu.com #也可指定url,此url也可以是外网地址\
      strip-prefix: false #true:代理转发时去掉前缀,false:代理转发时不去掉前缀
      sensitiveHeaders:  #默认zuul会屏蔽cookie,cookie不会传到下游服务,这里设置为空则取消默认的黑名单,如果设置了具体的头信息则不会传到下游服务
      #   ignoredHeaders: 默认为空表示不过虑任何头

serviceId:推荐使用serviceId,zuul会从Eureka中找到服务id对应的ip和端口。

strip-prefix: false #true:代理转发时去掉前缀,false:代理转发时不去掉前缀,例如,为true请 求/course/coursebase/get/…,代理转发到/coursebase/get/,如果为false则代理转发到/course/coursebase/get

sensitiveHeaders:敏感头设置,默认会过虑掉cookie,这里设置为空表示不过虑

ignoredHeaders:可以设置过虑的头信息,默认为空表示不过虑任何头

4、测试

请求:http://localhost:50201/api/course/coursepic/list/4028e58161bd22e60161bd23672a0001

查询课程图片信息

http://localhost:50201/api是网关地址,通过路由转发到xc-service-manage-course服务获取到请求地址http://localhost:50201,所以要使用到网关,在请求地址上添加/api即可

由于课程管理已经添加了授课拦截,这里为了测试网关功能暂时将“/course/coursepic/list”的url排除认证

在课程管理服务的ResourceServerConfig类中添加"/course/coursepic/list/*",代码如下:

@Override
public void configure(HttpSecurity http) throws Exception {
     //所有请求必须认证通过
     http.authorizeRequests()
             //下边的路径放行
             .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
                     "/swagger-resources","/swagger-resources/configuration/security",
                     "/swagger-ui.html","/webjars/**","/course/coursepic/list/**").permitAll()
             .anyRequest().authenticated();
}

5、yml文件中添加完整路由:

manage-cms:
      path: /cms/**
      serviceId: xc-service-manage-cms
      strip-prefix: false
      sensitiveHeaders:
manage-sys:
   path: /sys/**
   serviceId: xc-service-manage-cms
   strip-prefix: false
   sensitiveHeaders:
service-ucenter:
   path: /ucenter/**
   serviceId: xc-service-ucenter
   sensitiveHeaders:
   strip-prefix: false
xc-service-manage-order:
   path: /order/**
   serviceId: xc-service-manage-order
   sensitiveHeaders:
   strip-prefix: false


过滤器

Zuul的核心就是过虑器,通过过虑器实现请求过虑,身份校验等。

ZuulFilter

自定义过虑器需要继承 ZuulFilter,ZuulFilter是一个抽象类,需要覆盖它的四个方法,如下:

1、shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true表示要执行此过虑器,否则不执行。

2、run:过滤器的业务逻辑。

3、filterType:返回字符串代表过滤器的类型,如下

pre:请求在被路由之前执行

routing:在路由请求时调用

post:在routing和errror过滤器之后调用

error:处理请求时发生错误调用

4、filterOrder:此方法返回整型数值,通过此数值来定义过滤器的执行顺序,数字越小优先级越高。

测试

过虑所有请求,判断头部信息是否有Authorization,如果没有则拒绝访问,否则转发到微服务。

定义过虑器,使用@Component标识为bean。

编写过滤器测试类:LoginFilterTest

测试请求:http://localhost:50201/api/course/coursebase/get/4028e581617f945f01617f9dabc40000查询课程信息

1、Header中不设置Authorization

2、Header中设置Authorization

成功响应课程信息。


身份校验

本小节实现网关连接Redis校验令牌:

1、从cookie查询用户身份令牌是否存在,不存在则拒绝访问

2、从http header查询jwt令牌是否存在,不存在则拒绝访问

3、从Redis查询user_token令牌是否过期,过期则拒绝访问

1、在yml文件中配置redis参数:

redis:
    host: ${REDIS_HOST:127.0.0.1}
    port: ${REDIS_PORT:6379}
    timeout: 5000 #连接超时 毫秒
    jedis:
      pool:
        maxActive: 3
        maxIdle: 3
        minIdle: 1
        maxWait: -1 #连接池最大等行时间 -1没有限制

2、使用StringRedisTemplate查询key的有效期

在AuthService类中添加getTokenFromCookie、getJwtFromHeader和getExpire方法

说明:由于令牌存储时采用String序列化策略,所以这里用StringRedisTemplate来查询,使用RedisTemplate无法完成查询

3、定义LoginFilter类

4、配置代理

通过nginx转发到gateway,在www.xuecheng.com虚拟主机来配置

#微服务网关
upstream api_server_pool{
  server 127.0.0.1:50201 weight=10; 
}
#微服务网关 
location /api { 
  proxy_pass http://api_server_pool; 
}

使用postman测试:

Get请求:http://www.xuecheng.com/api/course/coursebase/get/4028e581617f945f01617f9dabc40000

注意:这里通过网关请求了course/coursebase/get地址,课程管理url根据自己的开发情况去配置

1、正常流程测试

a、执行登录之前向cookie写入身份令牌uid

Post请求:http://ucenter.xuecheng.com/openapi/auth/userlogin

并从redis获取jwt令牌的内容

b、手动在postman添加header

成功查询:

2、异常流程测试

手动删除header或清除cookie观察测试结果

Spring Boot 面试精讲


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
Java Maven
<7>springcloud中使用zuul网关实现反向代理和zuul过滤器
在之前一篇博客搭建的springcloud聚合项目基础上
|
存储 SpringCloudAlibaba API
SpringCloud Alibaba二十五 | 网关Restful接口拦截
SpringCloud Alibaba二十五 | 网关Restful接口拦截
243 0
|
Java 测试技术 API
|
算法 Java API
Spring Cloud Zuul如何实现开放平台接口的拦截校验(上)
Spring Cloud Zuul如何实现开放平台接口的拦截校验
188 0
|
Java API 数据安全/隐私保护
Spring Cloud Zuul如何实现开放平台接口的拦截校验(下)
Spring Cloud Zuul如何实现开放平台接口的拦截校验
96 0
SpringCloud学习笔记(三)-网关Zuul(下)
Zuul在SpringCloud中起到网关的作用,可用于请求路由转发、过滤、安全检查等作用,通过@EnableZuulProxy来开启网关的配置。
SpringCloud学习笔记(三)-网关Zuul(下)
|
运维 负载均衡 安全
27、网关zuul入门
为了解决请求路由和安全过滤,Spring Cloud推出了一个API gateway组件:Spring Cloud Zuul。
169 0
27、网关zuul入门