spring-cloud-starter-oauth2搭建授权中心服务
A 抖音APP
B 微信APP
C 微信授权中心
1授权码(authorization-code):
A前端跳转C授权地址,授权中心唤醒B登录后授权,跳转指定的重定向地址(一般就是A)携带一个code,A后端再用client_secret、code获取token 最最主流的应用模式
a.
http://127.0.0.1:8081/oauth/authorize?response_type=code&client_id=test&redirect_uri=http://127.0.0.1:8082/test&scope=read
b.
http://127.0.0.1:8082/test?code=drQ9y6
c.
http://127.0.0.1:8081/oauth/token?client_id=test&client_secret=test&grant_type=authorization_code&code=CGIFwy&redirect_uri=http://127.0.0.1:8082/test
2隐藏式(implicit):
A前端跳转C授权地址,授权中心唤醒B登录后授权,直接跳转指定的重定向地址(一般就是A) #号携带token 适合纯前端应用
http://127.0.0.1:8081/oauth/authorize?response_type=token&client_id=test&redirect_uri=http://127.0.0.1:8082/test&scope=read
3密码式(password):
A前端直接要求用户把登录账号密码填充,然后请求C拿到token 非常不安全,适合高可信任的三方比如微服务网关zuul-gataway等
http://127.0.0.1:8081/oauth/token?grant_type=password&username=admin&password=admin&client_id=test&client_secret=test
4.客户端凭证(client credentials):
明显可以看出整个过程不涉及用户信息,这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
http://127.0.0.1:8081/oauth/token?grant_type=client_credentials&client_id=test&client_secret=test
实测tips
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
较新的版本需要注意授权服务器需要配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.requestMatchers().anyRequest()
.and()
.authorizeRequests()
.antMatchers("/oauth/**","/oauth/authorize").authenticated();
http.formLogin();
} authenticated 而不是 permitAll
否则提示
{"code":500,"msg":"User must be authenticated with Spring Security before authorization can be completed.","data":null,"timestamp":1603527083994}
同时,假如要在授权服务上做资源服务配置,
@EnableWebSecurity
@Order(2)
@EnableResourceServer
@Order(6)
即前者初始化要优先
否则提示
<oauth>
<error_description>Full authentication is required to access this resource</error_description>
<error>unauthorized</error>
</oauth>
参考文档
http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
https://blog.csdn.net/qq_34997906/article/details/89609297
后续测试方向
1.微服务整合,资源服务配置,打算网关就做纯网关路由,授权中心不和用户资源服务做关联,甚至可以不注册到eureka
2.权限范围测试及各个模式异同
2020-10-28
完成微服务整合以后我们在资源服务上面开启安全注解,这样我们就能愉快的使用注解来细颗粒的控制权限了
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
客户端方式 client authorities以client表的authorities字段为准
授权码、隐藏式、密码登陆模式 authorities以user对应的role表为准
@GetMapping("/helloUser")
@Secured({"ROLE_normal","ROLE_admin"})
public String helloUser() {
return "hello,user";
}
说明:拥有normal或者admin角色的用户都可以方法helloUser()方法。另外需要注意的是这里匹配的字符串需要添加前缀“ROLE_“。如果我们要求,只有同时拥有admin & noremal的用户才能方法helloUser()方法,这时候@Secured就无能为力了。
我在申请token的时候指定read update
此时如果资源服务器的scope要求write或者create的scope权限就无权访问了。
3.自定义登录授权
增2020-11-03
经过实践查阅认证自定义登录的概念有两类,第一种是针对Oauth四种模式的扩展,即获取token的扩展,第二种是针对授权码模式和隐藏模式在跳转认证服务时登录认证时的自定义扩展,即spring security的登录扩展。两种都能集成短信、社交、扫码、用户密码的扩展,前者对调用者来说每次都要改调用方式,而后者授权流程不变,只是在认证服务的登录页面提供多元登录操作,只需要服务方去集成,调用者不需要做任何调整。说的有点抽象哈,请看下图。
a.纵向扩展比较简单,继承AbstractTokenGranter重写getOAuth2Authentication方法,然后将新的授权方法塞入。
效果如下
b.横向扩展,需要自定义登陆页面和授权页面(后期接入许多认证方式都要加对应前端的东西),指定spring security的登陆页面地址和UsernamePasswordAuthenticationFilter的目标过滤地址,如果新增扩展自定义的过滤器需要注释否则会走再经过上面提到spring security的UsernamePasswordAuthenticationFilter。还要再指定经过过滤器以后跳转的授权页地址替换默认的“oauth/comfirm_access”。
然后校验的核心就是MyUsernamePasswordAuthenticationFilter自定义过滤器和MyAuthenticationManager自定义的认证类,然后加入配置
这样授权码和隐藏模式在登陆的时候可以自定义我们的规则,成功后点击授权就可以发放code或者token了。
2021-01-29
尝试将oauth服务接入eureka集群,gateway过滤认证且允许传递header。oauth自定义接口测试正常。前端通过gateway顺利获取到token。
再尝试经过dateway授权码模式获取code时发现域名地址出现了变化。这里就涉及到eureka注册服务的ip和主机名策略。
eureka:
instance:
prefer-ip-address: true
ip-address: localhost #为了让授权码模式跳转在同一个域名 配置成和gateway同入口的域名
因为新老服务的关系,eureka client注册存在差异。老版本默认ip注册,新版本默认主机名注册。导致gateway ip域名请求时的session在oauth主机名下跳转登陆页面获取不到session
导致报错404.把oauth的实例改成和gateway同一个域名ip可解决。