OAuth2.0支持如下四种授权模式,其中安全级别最高的是授权码模式。我们先了解一下在代码中如何简单的实现四种授权模式,下一篇在介绍关于四种授权模式的选型。
注意:不管通过哪种授权模式获取授权,第三方应用在获取授权之前,都必须在系统备案,拿到客户端ID(Client ID)和客户端密钥(Client Secret)后再通过OAuth2.0获取令牌,这是避免令牌被滥用,只有备案的第三方应用才可以获取令牌。
jdk:1.8 开发工具:Intellij IDEA 2018.2 springboot版本:1.5.10
由于Spring Security对OAuth2.0进行了实现,所以我这里直接使用Spring-Security-OAuth2.0进行演示。
这种方式是最常用的也是安全性也最高的方式。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
流程
第一步,创建父级Maven工程microservice,如何使用IDEA创建Maven项目很简单,这里不说明了,直接贴一下pom文件
<groupId>com.curise.microservice</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.boot.version>1.5.10.RELEASE</spring.boot.version>
<lombok.version>1.16.20</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
其中引入了spring-boot-starter-parent的pom依赖,其余没有特殊的地方。
第二步,创建microservice的Module项目authcode_server,贴一下pom文件
<parent>
<artifactId>microservice-parent</artifactId>
<groupId>com.curise.microservice</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>authcode_server</artifactId>
<description>OAuth2授权码模式</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- for OAuth 2.0 -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
其中引入了spring-boot-starter-security和spring-security-oauth2依赖
第三步,创建授权服务器
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 客户端id
.withClient("app")
// 客户端密钥
.secret("123")
// 权限
.scopes("read","write")
// 获取授权码后重定向地址
.redirectUris("http://localhost:9000/callback")
// 授权码和刷新token
.authorizedGrantTypes("authorization_code","refresh_token");
}
}
通过@EnableAuthorizationServer注解开启授权管理器,其中客户端信息是放在了内存中,当然生产级别肯定不能这么做,这里只是学习级别的代码。
第四步,创建资源管理器
@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.requestMatchers()
// /api/**请求需要OAuth鉴权
.antMatchers("/api/**");
}
}
通过@EnableResourceServer注解开启资源管理器,并设置对/api/**的请求url进行拦截需要鉴权,当前生产上一般授权管理器和资源管理器是分开的。
第五步,创建配置文件,配置端口号和Spring Security的信息
server.port=8080
security.user.name=root
security.user.password=root
第六步,添加Controller
@RestController
public class UserController {
@GetMapping("/api/userInfo")
public ResponseEntity<UserInfo> getUserInfo(){
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String email = user.getUsername() + "@qq.com";
UserInfo userInfo = new UserInfo();
userInfo.setUsername(user.getUsername());
userInfo.setEmail(email);
return ResponseEntity.ok(userInfo);
}
}
第七步,启动服务,现在按照规定的流程去获取授权码和Access Token
步骤1,通过浏览器发送请求
http://localhost:8080/oauth/authorize?client_id=app&
redirect_uri=http://localhost:9000/callback&
其中client_id是第三方应用在授权系统中备案的client名称
redirect_uri是授权成功或失败后跳转回来的地址,localhost:9000我是没有启动服务的,只是为了拿到授权码
response_type是请求返回授权码
scope是请求的授权范围
state是自定义的信息,会跟着 redirect_uri返回。
如图:这里授权服务要求输入用户名和密码,这里输入配置文件里配置的root:root
这里选择Approve并授权,页面会跳转如下地址,就可以拿到授权码了。
步骤2:通过授权码获取Access Token,这里使用Postman工具
Header添加Content-Type,点击发送获得了access_token就是令牌。
步骤3:通过令牌获取用户信息
步骤4:修改一下token,后面添加111,提示token无效
令牌的有效期默认是12个小时,如果令牌到期了,提示用户再去重新走一遍流程,体验不太好,所以OAuth2.0支持刷新令牌,使用刷新令牌去申请一个新令牌。
先修改一下授权服务器的配置,把令牌有效期修改为10秒(默认12小时),刷新令牌(默认30天),同时必须配置支持refresh_token。
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 客户端id
.withClient("app")
// 客户端密钥
.secret("123")
// 权限
.scopes("read","write")
// 获取授权码后重定向地址
.redirectUris("http://localhost:9000/callback")
//令牌有效期秒
.accessTokenValiditySeconds(10)
// 刷新令牌有效期秒
//.refreshTokenValiditySeconds(1000)
// 授权码和刷新token
.authorizedGrantTypes("authorization_code","refresh_token");
}
}
启动应用,再次获取授权码和令牌
等待令牌超时后调用获取用户信息接口,提示token无效
通过发送请求去获得新的token
再次获取用户信息
代码已经共享到GitHub,地址:https://github.com/WYA1993/microservice
参考文章和课程:
OAuth2.0详解(授权模式篇)
《微服务架构实战160讲》——杨波
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/WYA1993/article/details/100561329
内容来源于网络,如有侵权,请联系作者删除!