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

现在做的都是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身份验证的凭证https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Authorization),用户名输入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
@EnableResourceServer
public 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的样式也是默认的。

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

Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商的更多相关文章

  1. Spring Security构建Rest服务-1300-Spring Security OAuth开发APP认证框架之JWT实现单点登录

    基于JWT实现SSO 在淘宝( https://www.taobao.com )上点击登录,已经跳到了 https://login.taobao.com,这是又一个服务器.只要在淘宝登录了,就能直接访 ...

  2. Spring Security构建Rest服务-1200-SpringSecurity OAuth开发APP认证框架

    基于服务器Session的认证方式: 前边说的用户名密码登录.短信登录.第三方登录,都是普通的登录,是基于服务器Session保存用户信息的登录方式.登录信息都是存在服务器的session(服务器的一 ...

  3. Spring Security构建Rest服务-1202-Spring Security OAuth开发APP认证框架之重构3种登录方式

    SpringSecurityOAuth核心源码解析 蓝色表示接口,绿色表示类 1,TokenEndpoint 整个入口点,相当于一个controller,不同的授权模式获取token的地址都是 /oa ...

  4. Spring Security构建Rest服务-1203-Spring Security OAuth开发APP认证框架之短信验证码登录

    浏览器模式下验证码存储策略 浏览器模式下,生成的短信验证码或者图形验证码是存在session里的,用户接收到验证码后携带过来做校验. APP模式下验证码存储策略 在app场景下里是没有cookie信息 ...

  5. Spring Security构建Rest服务-1205-Spring Security OAuth开发APP认证框架之Token处理

    token处理之二使用JWT替换默认的token JWT(Json Web Token) 特点: 1,自包含:jwt token包含有意义的信息 spring security oauth默认生成的t ...

  6. Spring Security构建Rest服务-1204-Spring Security OAuth开发APP认证框架之Token处理

    token处理之一基本参数配置 处理token时间.存储策略,客户端配置等 以前的都是spring security oauth默认的token生成策略,token默认在org.springframe ...

  7. ASP.NET Core的身份认证框架IdentityServer4--(3)令牌服务配置访问控制跟UI添加

    使用密码保护API OAuth 2.0 资源所有者密码授权允许一个客户端发送用户名和密码到IdentityServer并获得一个表示该用户的可以用于访问api的Token. 该规范建议仅对" ...

  8. spring boot:构建多模块项目(spring boot 2.3.1)

    一,为什么要使用多模块? 1,结构更清晰,方便管理    如果只是一个小项目当然没有问题,    但如果功能越增越多则管理越来越复杂,    多模块可以使项目中模块间的结构分离   2,把项目划分成多 ...

  9. Android 从硬件到应用程序:一步一步爬上去 6 -- 我写的APP测试框架层硬件服务(终点)

    创Android Applicationproject:采用Eclipse的Android插入ADT创Androidproject,project名字Gpio,创建完成后,project文件夹pack ...

随机推荐

  1. spring boot入门与进阶

    视频课程包含: SpringBoot入门.SpringBoot进阶.Spring Cloud微服务.Spring Ecosystem 微服务相关.Spring Boot 入门 IDEA 版本.Spri ...

  2. ROS教程

    Learning ROS 学习ROS Depending on your learning style and preferences, you can take two approaches to ...

  3. new Date()之参数传递

    JavaScript下,new Date([params]),参数传递有以下五种方式: 1.new Date("month dd,yyyy hh:mm:ss"); 2.new Da ...

  4. 百度离线地图,web

    1.首先获取百度 JavaScript API 首先用浏览器打开 http://api.map.baidu.com/api?v=1.3 其中 http://api.map.baidu.com/gets ...

  5. Linux 用 sftp scp命令 互传文件

    sftp它类似于 ftp, 但它进行加密传输,比FTP有更高的安全性. sftp 是SSH服务的子程序 常用命令 pwd 查看当前工作目录 ls 查看远程当前目录下的所以文件或者目录信息 lls 查看 ...

  6. hdu 4974 贪心

    http://acm.hdu.edu.cn/showproblem.php?pid=4974 n个人进行选秀,有一个人做裁判,每次有两人进行对决,裁判可以选择为两人打分,可以同时加上1分,或者单独为一 ...

  7. hdu 5011 Nim+拿完分堆

    http://acm.hdu.edu.cn/showproblem.php?pid=5011 有N堆珠子,两个人轮流拿,最少拿一个,可以全拿,每次只能从一个堆里拿,不能从多堆同时拿:拿完之后该人还有一 ...

  8. 软件工程 wc.exe 代码统计作业

    软件工程 wc.exe 代码统计作业分享 1. Github 项目地址 https://github.com/EdwardLiu-Aurora/WordCount 更好地阅读本文,可点击这里 基本要求 ...

  9. Linux系统下ping命令报错 name or service not know

    问题描述 CentOS,但是当执行ping命令的时候,提示name or service not known 解决方法 1.添加DNS服务器 vi /etc/resolv.conf 进入编辑模式,增加 ...

  10. 学习总结---INNODB 事务并发

    目前在做一个OLTP的数据库系统,批量读写和随机读写并发,情况比较复杂.INNODB是我们的MYSQL引擎,他的主要特点是读操作可以不受阻塞,而修改操作会加锁.如何才能最高效的使用innodb是我们需 ...