【OAuth2】:赋予用户控制权的安全通行证--代码模拟篇
2023-12-26 23:46:10
🥳🥳Welcome Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于OAuth2的相关操作吧?
?上篇已经讲了oauth2的相关知识,详解了oauth2的四种授权模式中的授权码模式,那么这一篇我们就来讲一下授权码模式的代码实现,但是为了更好的讲解其中的相关知识点,这里用的是模拟代码【没有连接数据库进行验证】
目录
🥳🥳Welcome Huihui's Code World ! !🥳🥳
一.代码准备
1.client
1.1pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>client</name> <description>client</description> <parent> <artifactId>Oauth</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.example.client.ClientApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
1.2controller
package com.example.client.controller; import lombok.extern.slf4j.Slf4j; import org.apache.oltu.oauth2.client.HttpClient; import org.apache.oltu.oauth2.client.OAuthClient; import org.apache.oltu.oauth2.client.URLConnectionClient; import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; import org.apache.oltu.oauth2.client.request.OAuthClientRequest; import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; import org.apache.oltu.oauth2.client.response.OAuthResourceResponse; import org.apache.oltu.oauth2.common.OAuth; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.types.GrantType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; /** * 获取授权的控制器 */ @Controller @RequestMapping("/client") @SuppressWarnings("all") @Slf4j public class GetAuthorizationController { /** * 客户端: 8080 * 资源拥有者: 8081 * 认证服务器: 8082 * 资源服务器: 8083 */ private static String CLIENT_ID = "clientId"; private static String CLIENT_SECRET = "clientSecret"; private static String CODE_URL = "code"; private static String RESPONSE_TYPE = "code"; /*认证服务器地址*/ private static String AUTH_SERVER_URL = "http://localhost:8082/authServer/token"; /*资源拥有者地址*/ private static String RESOURCE_OWNER_URL = "http://localhost:8081/owner/"; /*资源服务器地址*/ private static String RESOURCE_SERVER_URL = "http://localhost:8083/resourceServer/userinfo"; /*授权码回调地址*/ private static String CALLBACKCODE = "http://localhost:8080/client/callbackCode"; /*获取资源地址*/ private static String GETRESOURCE = "http://localhost:8080/client/getResource"; /** * 客户向资源所有者获取授权码 */ @GetMapping("/getCode") public String getCode() throws OAuthSystemException { // 创建OAuthClientRequest对象,设置授权码请求的相关参数 OAuthClientRequest oAuthClientRequest = OAuthClientRequest .authorizationLocation(CODE_URL) // 授权码请求的授权服务器地址 .setClientId(CLIENT_ID) // 设置客户端ID .setRedirectURI(CALLBACKCODE) // 设置重定向URI .setResponseType(RESPONSE_TYPE) // 设置响应类型为授权码 .buildQueryMessage(); // 构建查询消息 String uriString = oAuthClientRequest.getLocationUri(); // 获取授权码请求的URI字符串 // 重定向到资源所有者,获取验证码 return "redirect:" + RESOURCE_OWNER_URL + uriString; } /** * 1. 资源所有者在生成授权码之后,会回调该接口将授权码传回给客户 * 2. 客户获取授权码之后,使用该接口向认证服务器申请令牌 */ @RequestMapping("/callbackCode") public String callbackCode(HttpServletRequest request) throws OAuthSystemException, OAuthProblemException { // 从请求中获取授权码 String code = request.getParameter("code"); log.info(" --- 从资源拥有者获取code: {} -----------", code); // 创建OAuthClient对象,用于与认证服务器进行通信 OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); // 创建OAuthClientRequest对象,设置令牌请求的相关参数 OAuthClientRequest tokenRequest = OAuthClientRequest .tokenLocation(AUTH_SERVER_URL) // 令牌请求的认证服务器地址 .setClientId(CLIENT_ID) // 设置客户端ID .setClientSecret(CLIENT_SECRET) // 设置客户端密钥 .setGrantType(GrantType.AUTHORIZATION_CODE) // 设置授权类型为授权码 .setCode(code) // 设置授权码 .setRedirectURI(CALLBACKCODE) // 设置重定向URI .buildQueryMessage(); // 构建查询消息 // 通过Code,向认证服务器申请令牌 OAuthJSONAccessTokenResponse tokenResp = oAuthClient.accessToken(tokenRequest, OAuth.HttpMethod.POST); // 发送请求并获取响应 // 从响应中获取访问令牌 String accessToken = tokenResp.getAccessToken(); log.info("客户获取的访问令牌:" + accessToken); return "redirect:" + GETRESOURCE + "?accessToken=" + accessToken; } /** * 使用令牌获取资源服务器中的数据 */ @GetMapping("/getResource") @ResponseBody public String getResource(String accessToken) throws OAuthSystemException, OAuthProblemException { log.info("客户使用令牌向资源服务器获取数据 token = " + accessToken); // 创建OAuthClient对象,用于与资源服务器进行通信 OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); // 创建OAuthClientRequest对象,设置用户信息请求的相关参数 OAuthClientRequest userInfoRequest = new OAuthBearerClientRequest(RESOURCE_SERVER_URL) // 用户信息请求的资源服务器地址 .setAccessToken(accessToken) // 设置访问令牌 .buildHeaderMessage(); // 构建请求头消息 // 向资源服务器发送请求并获取响应 OAuthResourceResponse resourceResponse = oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class); // 从响应中获取用户信息 String userInfo = resourceResponse.getBody(); log.info("客户获取的资源服务器的数据: " + userInfo); return userInfo; } }
2.resource-owner
2.1pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>resource-owner</artifactId> <version>0.0.1-SNAPSHOT</version> <name>resource-owner</name> <description>resource-owner</description> <parent> <artifactId>Oauth</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.authzserver</artifactId> </dependency> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.resourceserver</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.example.owner.ResourceOwnerApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
2.2controller
package com.example.owner.controller; import lombok.extern.slf4j.Slf4j; import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest; import org.apache.oltu.oauth2.as.response.OAuthASResponse; import org.apache.oltu.oauth2.common.OAuth; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.OAuthResponse; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Controller // 声明这是一个控制器类 @RequestMapping("/owner") // 设置请求映射路径为 /owner @Slf4j // 使用 Lombok 的 @Slf4j 注解,简化日志记录 @SuppressWarnings("all") // 忽略所有警告 public class CodeController { @GetMapping("/code") // 定义一个处理 GET 请求的方法,映射路径为 /code public String sendCode(HttpServletRequest request) { log.info("resource owner send code"); // 记录日志信息 try { OAuthAuthzRequest oathReq = new OAuthAuthzRequest(request); // 从请求中获取 OAuthAuthzRequest 对象 if (StringUtils.hasLength(oathReq.getClientId())) { // 如果客户端ID存在 //设置授权码 String code = "authorizationCode"; String responseType = oathReq.getResponseType(); //获取构建响应的对象 OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_OK); builder.setCode(code); // 设置授权码 String redirectURI = oathReq.getParam(OAuth.OAUTH_REDIRECT_URI); // 获取重定向URI OAuthResponse oauthResp = builder.location(redirectURI).buildQueryMessage(); // 构建查询消息 log.info("resource owner send code "); // 记录日志信息 String uri = oauthResp.getLocationUri(); // 获取重定向URI return "redirect:" + uri; // 返回重定向URL } } catch (OAuthSystemException e) { // 捕获 OAuthSystemException 异常 e.printStackTrace(); // 打印异常堆栈信息 } catch (OAuthProblemException e) { // 捕获 OAuthProblemException 异常 e.printStackTrace(); // 打印异常堆栈信息 } return null; // 如果发生异常或客户端ID不存在,返回 null } }
3.authorization-server
3.1pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>authorization-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>authorization-server</name> <description>authorization-server</description> <parent> <artifactId>Oauth</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.authzserver</artifactId> </dependency> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.resourceserver</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.example.authorization.AuthorizationServerApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
3.2controller
?package com.example.authorization.controller; import lombok.extern.slf4j.Slf4j; import org.apache.oltu.oauth2.as.issuer.MD5Generator; import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl; import org.apache.oltu.oauth2.as.request.OAuthTokenRequest; import org.apache.oltu.oauth2.as.response.OAuthASResponse; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.OAuthResponse; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Controller // 声明这是一个控制器类 @RequestMapping("/authServer") // 设置请求映射路径为 /authServer @Slf4j // 使用 Lombok 的 @Slf4j 注解,简化日志记录 @SuppressWarnings("all") // 忽略所有警告 public class AuthController { @PostMapping("/token") // 定义一个处理 POST 请求的方法,映射路径为 /token public HttpEntity getAccessToken(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException { log.info("认证服务器,接收到客户的令牌请求 .... "); // 记录日志信息 OAuthTokenRequest tokenReq = new OAuthTokenRequest(request); // 从请求中获取 OAuthTokenRequest 对象 String clientSecret = tokenReq.getClientSecret(); // 获取客户端密钥 if (StringUtils.hasLength(clientSecret)) { // 如果客户端密钥存在 OAuthIssuerImpl oAuthIssuer = new OAuthIssuerImpl(new MD5Generator()); // 创建一个 OAuthIssuerImpl 对象,使用 MD5Generator 生成签名算法 String token = oAuthIssuer.accessToken(); // 生成访问令牌 log.info("token = " + token); // 记录日志信息 //构造保护令牌的响应对象 OAuthResponse oAuthResponse = OAuthASResponse .tokenResponse(HttpServletResponse.SC_OK) // 设置响应状态码为 200 OK .setAccessToken(token) // 设置访问令牌 .buildJSONMessage(); // 构建 JSON 格式的响应消息 return new ResponseEntity(oAuthResponse.getBody(), HttpStatus.valueOf(oAuthResponse.getResponseStatus())); // 返回响应实体 } return null; // 如果客户端密钥不存在,返回 null } }
4.resource-server
4.1pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>resource-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>resource-server</name> <description>resource-server</description> <parent> <artifactId>Oauth</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.authzserver</artifactId> </dependency> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.resourceserver</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.example.resource.ResourceServerApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
4.2controller
package com.example.resource.controller; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.types.ParameterStyle; import org.apache.oltu.oauth2.rs.request.OAuthAccessResourceRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; @RestController // 声明这是一个控制器类 @RequestMapping("/resourceServer") // 设置请求映射路径为 /resourceServer @SuppressWarnings("all") // 忽略所有警告 public class UserController { @GetMapping("/userinfo") // 定义一个处理 GET 请求的方法,映射路径为 /userinfo public Object getUserInfo(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException { // 创建一个 OAuthAccessResourceRequest 对象,用于处理 OAuth 认证请求 OAuthAccessResourceRequest oAuthAccessResourceRequest = new OAuthAccessResourceRequest(request, ParameterStyle.HEADER); // 获取访问令牌 String accessToken = oAuthAccessResourceRequest.getAccessToken(); // 创建一个 Map 对象,用于存储用户信息 Map<String, Object> map = new HashMap<>(); // 向 Map 中添加用户信息 map.put("name", "zhengsuanfeng"); map.put("phone", "13576472774"); map.put("addr", "长沙岳麓区"); // 返回用户信息 return map; } }
5.整体项目的pom依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>Oauth</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>client</module> <module>resource-owner</module> <module>authorization-server</module> <module>resource-server</module> </modules> <properties> <oauth2.version>0.31</oauth2.version> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.4.1</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.client</artifactId> <version>${oauth2.version}</version> </dependency> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.authzserver</artifactId> <version>${oauth2.version}</version> </dependency> <dependency> <groupId>org.apache.oltu.oauth2</groupId> <artifactId>org.apache.oltu.oauth2.resourceserver</artifactId> <version>${oauth2.version}</version> </dependency> </dependencies> </dependencyManagement> </project>
二.授权码模式的模拟代码流程讲解?
1.用户访问页面
2.访问的页面将请求重定向到认证服务器
3.认证服务器向用户展示授权页面,等待用户授权
4.用户授权完成认证服务器带上client_id发送给应用服务器资源服务器?生成一个code
然后,用户拿到code
5.获取令牌(Token)
将code、client_id、client_secret传给认证服务器换取access_token
?6.将access_token传给资源服务器
7.验证token,访问真正的资源页面拿到数据
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊????
文章来源:https://blog.csdn.net/m0_74315688/article/details/135218605
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!