博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商...
阅读量:5009 次
发布时间:2019-06-12

本文共 4184 字,大约阅读时间需要 13 分钟。

实现服务提供商,就是要实现认证服务器、资源服务器。

现在做的都是app的东西,所以在app项目写代码

 认证服务器:

新建 ImoocAuthenticationServerConfig 类,@EnableAuthorizationServer 注解就说明该项目是一个 认证服务器:

@Configuration@EnableAuthorizationServer //这个注解就是实现了一个认证服务器public class ImoocAuthenticationServerConfig {}

OAuth协议流程:

实现授权码模式:

  服务提供商需要提供两个服务:

  1,用户调过来点击授权的地址 (如qq微信登录的授权页)

  2,点完授权后带着授权码换取access_token的地址(对用户不可见)

加上了@EnableAuthorizationServer 注解的项目,启动后控制台会打印如下的信息:

/oauth/authorize 就是让用户授权的地址,启动应用,访问/oauth/authorize,需要一些参数: 

  • response_type:表示授权类型,必选项,此处的值固定为"code"
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

其中client_id 在启动应用时控制台会打印:

实现授权码模式第一步:获取授权码

拼接访问串:

localhost:8080/oauth/authorize?response_type=code&client_id=f835525e-cbdb-4609-8dae-fbf5ef2b2484&redirect_uri=http://example.com&scope=all

我们的应用相当于 服务提供商,它需要知道三件事

1,哪个应用在请求授权 :通过client_id,第三方应用在应用服务器上注册时分配的id,通过client_id 识别是哪个应用在请求授权

2,在请求哪个用户在给你授权:上图中的form表单就是确认系统中的哪个用户在授权

3,赋予哪些权限:scope参数标识赋予哪些权限

 demo项目引用app项目,启动的都是demo项目,

 demo项目里有处理认证的类MyUserDetailsService 类,用户名没有处理,只要密码是123456就行

 

private SocialUserDetails buildUser(String userId) {        String password = passwordEncoder.encode("123456");        System.err.println("加密后密码:  "+password);        //参数:用户名|密码|是否启用|账户是否过期|密码是否过期|账户是否锁定|权限集合        return new SocialUser(userId,password,true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));    }

 

在认证表单输入密码123456,用户名随便,点击登录,403 拒绝访问

原因是默认情况下,认证服务器上请求需要有ROLE_USER的角色才能访问,在MyUserDetailsService 里加上:

private SocialUserDetails buildUser(String userId) {        String password = passwordEncoder.encode("123456");        System.err.println("加密后密码:  "+password);        //参数:用户名|密码|是否启用|账户是否过期|密码是否过期|账户是否锁定|权限集合        return new SocialUser(userId,password,true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_USER"));    }

把client_id 配置到application.properties 配置文件:

security.oauth2.client.clientId = imooc

#注意clientSecret 大写
security.oauth2.client.clientSecret = imoocsecret

再次访问:http://localhost:8080/oauth/authorize?response_type=code&client_id=imooc&redirect_uri=http://example.com&scope=all

这个页面相当于qq登录授权页或微信登录的扫码页,询问是否同意授权,点击同意,返回到http://example.com,并携带了授权码

http://example.com/?code=lUDDeG

实现授权码模式第二步:授权码换取access_token:

此时就该拿着授权码去获取access_token了,post请求 /oauth/token ,使用Resetlet Client,在请求头里新建一个Authentication(Authorization 设置HTTP身份验证的凭证),用户名输入imooc,密码输入 imoocsecret

 

客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

  • grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
  • code:表示上一步获得的授权码,必选项。
  • redirect_uri:表示重定向URI,必选项,且必须与上边步骤中的该参数值保持一致。
  • client_id:表示客户端ID,必选项。
  • client_secret:客户端密钥

 完整的请求:

响应:

 
{
"access_token": "66e4e300-deb0-4bfa-a171-a6e5a34c922e",
"token_type": "bearer",
"refresh_token": "4bd03df8-f150-402f-8aee-6f16e4838b6e",
"expires_in": 43199,
"scope": "all"
}

 密码模式:

参数是用户名密码,其实是用户把在 服务提供商上的 用户名/密码 告诉了第三方,第三方拿着用户名密码去给服务提供商说用户已经授权了。

在app场景下是可用的,因为第三方是app,是公司前端,提供商是服务端,都是一伙的,不涉及安全问题

响应:

可以看到,用同一个用户名登录,响应的access_token是同一个,只要这个token还没过期。

 资源服务器:

和认证服务器类似

 

/** * 资源服务器,和认证服务器在物理上可以在一起也可以分开 * ClassName: ImoocResourceServerConfig  * @Description: TODO * @author lihaoyang * @date 2018年3月13日 */@Configuration@EnableResourceServerpublic class ImoocResourceServerConfig {}

 

启动demo项目,由于没有配置token存储策略,所以生成的token都是在内存中的,在这里重新用密码模式获取一下token:

http://127.0.0.1:8080/oauth/token

{
"access_token": "864defd9-b62a-4d59-a133-9247d9dc546d",
"token_type": "bearer",
"refresh_token": "4fd9b93b-ca72-4efe-ae11-d9ac491bdf2f",
"expires_in": 43199,
"scope": "all"
}
访问http://127.0.0.1:8080/user/me 获取用户信息
  @GetMapping("/me")    public Object getCurrentUser(@AuthenticationPrincipal UserDetails user) {        return user;    }

 

需要在请求头里加上参数token和返回的token_type   bearer,和token用空格隔开 ,因为Authorization格式为   
Authorization: <type> <credentials>

响应:

{"password": null,"username": "user","authorities":[{"authority": "ROLE_USER"},{"authority": "admin"}],"accountNonExpired": true,"accountNonLocked": true,"credentialsNonExpired": true,"enabled": true,"userId": "user"}

通过token 获取到了用户信息。

 到目前为止获取token和用token 访问服务已完成,但是都是用的OAuth标准的规范和spring security默认的实现。认证方式只能是OAuth规定的四种模式,还不能用手机验证码登录,token也是存在了内存里,是不行的。token的样式也是默认的。

下一步个性化实现,改造 用户名密码登录、短信验证码登录、第三方登录

转载于:https://www.cnblogs.com/lihaoyang/p/8549579.html

你可能感兴趣的文章
岗顶-一图一世界
查看>>
一步步构造自己的vue2.0+webpack环境
查看>>
分页类
查看>>
Python装饰器的个人小理解
查看>>
为什么百万医疗险越来越多,到底选哪款?
查看>>
如何检测 51单片机IO口的下降沿
查看>>
扫描识别控件Dynamic .NET TWAIN使用教程:如何将事件添加到应用程序中
查看>>
创建和修改主键 (SQL)
查看>>
2018-2019 ICPC, NEERC, Southern Subregional Contest(训练记录)
查看>>
20145233 《信息安全系统设计基础》第7周学习总结
查看>>
linux设备驱动程序第3版学习笔记(例程2--hellop.c)
查看>>
玩转storm
查看>>
第10章 使用Apache服务部署静态网站
查看>>
关于给予webApp框架的开发工具
查看>>
c语言编写的生成泊松分布随机数
查看>>
Maven入门笔记
查看>>
iOS webView的常见属性和方法
查看>>
理解position:relative
查看>>
Codeforces Round #344 (Div. 2) Messager KMP的应用
查看>>
20145308刘昊阳 《Java程序设计》第4周学习总结
查看>>