最近在自学微服务,参考资料是 《重新定义Spring Cloud实战》 ,在看到Zuul网关这一章时,我照着 Zuul+OAuth2.0+JWT实战 这一栏编码,发现复现不了书里的预期结果,网上求助资料很杂乱,经过一系列尝试大致解决问题,以下是我的采坑心得
书中工程git: https://github.com/cakin24/spring-cloud-code/tree/master/ch8-2
坑点一:error=“invalid_request”, error_description=“At least one redirect_uri must be registered with the client.”
现象: 根据demo,在访问http://localhost:5555时,会跳转到
http://localhost:5555/login
此时,如果填写账号密码,浏览器将会自动跳转到如下链接:
http://localhost:7777/uaa/oauth/authorize?client_id=test-zuul-server&redirect_uri=http://localhost:5555/login&response_type=code&state=qdw208
并且提示At least one redirect_uri must be registered with the client
解决办法:
auth-server继承了AuthorizationServerConfigurerAdapter的类configure(ClientDetailsServiceConfigurer clients)方法需要手动指定回调地址
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
//客户端ID
.withClient("test-zuul-server")
//客户端秘钥
.secret("secret")
//允许授权的范围,"read"-只读
.scopes("WRIGTH", "read")
//跳过用户确认授权操作页面,直接跳到redirect_uri
.autoApprove(true)
//指定用户的权限范围
.authorities("WRIGTH_READ","WRIGTH_WRITE")
//客户端允许的授权类型,implicit-隐藏式; authorization_code-授权码; password-密码式; client_credentials-凭证式; refresh_token-更新令牌
.authorizedGrantTypes("implicit","refresh_token","password", "authorization_code")
.redirectUris("http://localhost:5555/login");
}
坑点二:Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. There was an unexpected error (type=None, status=999).
原因: demo用的是spring security中默认配置的formLogin来实现表单登录。但是在demo中并没有开启formLogin默认配置,因此,spring无法找到登录页面上使用的静态资源之一。但是,404它尝试呈现错误页面并将请求转发给,而不是返回此资源的状态/error,故Spring Security拒绝此请求。因为用户未被授权。它将/error请求保存到会话中(用于成功登录后进行重定向),并将用户重定向到登录页面。
当然,用户看不到此重定向,因为状态302在后台完成的请求返回。但是主要问题是/error请求保存在会话中。
然后用户成功登录,并spring检查该属性的会话并重定向到/error页面。默认情况下,spring假设您在静态资源中的某处有这样的页面。如果没有该页面,您将看到状态码为999的此奇怪错误。
解决办法:
auth服务继承WebSecurityConfigurerAdapter的类重写
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() //禁用跨站csrf攻击防御
.formLogin(//开启formLogin默认配置
.and()
.authorizeRequests()//配置权限
.anyRequest().authenticated();//任何请求都需要授权
}
坑点三: “error_description”: “Full authentication is required to access this resource”
原因: 敏感头信息如Authorization,Cookie,Set-Cookie默认zuul是不转发的,所以其他服务中也就获取不到这部分信息
解决办法:
在zuu-server的yml文件中新增如下配置:
zuul:
routes:
sensitive-headers: //为空,敏感头信息Authorization,Cookie,Set-Cookie 就不会被过滤
坑点四:Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.where was an unexpected error (type=Not Found, status=404).
原因: 在解决完上述问题后,重新输入账号密码,发现系统最终调用了http://localhost:5555/login?code=Hr2gps&state=m75lph,此时已经拿到授权码,说明第一步拿授权码已经成功。需要第二步拿到token。
但是页面会展示如上异常。
此时,访问http://localhost:5555/client/test会发现资源已经能拿到,根据clint服务打印的请求头中也已经有了Authorization,至于出现这个404错误,是因为我们是通过localhost:5555为源地址出发的授权,在拿到token后,浏览器会跳转回到localhost:5555,当没有资源时,就会显示404