最近在学习Oauth,趁有时间把一些实践经验和理解记录下来,目前oauth最新的版本是2.0,相比1.0更简单更安全,在企业的业务系统中可用来实现SSO。
1、OAuth的简述
OAuth(Open Authorization,开放授权)是为用户资源的授权定义了一个安全、开放及简单的标准,第三方无需知道用户的账号及密码,就可获取到用户的授权信息,并且这是安全的。
2、名称定义
在详细讲解OAuth 2.0之前,需要了解几个专用名词。它们对读懂后面的讲解,至关重要。
(1)Third-party application:第三方应用程序,本文中又称"客户端"(client)。
(2)Resource Owner:资源所有者,本文中又称"用户"(user)。
(3)User Agent:用户代理,本文中就是指浏览器。
(4)Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
(5)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。
知道了上面这些名词,就不难理解,OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务商提供商"进行互动。
3、OAuth的原理
上图是Oauth2.0其中的授权码模式(authorization code),因为这个模式比较常用,我主要学习这个为主,图中我分为5个步骤讲解
【A】 用户请求访问客户端,或者将前者导向至认证服务器,带上参数:client_id和redirect_url
【C】 用户选择同意授权,认证服务器把用户导向至redirect_url,并且附上授权码(authorization code)
【D】 客户端向认证服务器请求access token,需要带上参数:client_id,client_secret,redirect_uri,和上一步获取的authorization code;认证服务器检查参数正确则返回access tonken表示授权成功
【E】 客户端使用access token请求资源服务器获取用户资源。
3、OAuth2.0简单实现(java)
国外有几个开源的java版的oauth实现,可以帮助较快的搭建一个oauth服务器,例如以下几个(可点击打开对应官网)
· Java
· Apis Authorization Server (v2-31)
· Restlet Framework (draft 30)
Apache Oltu
目前我只是尝试了Oltu,比较轻量级,也不需要依赖其他服务,比较简单,但是官方的文档实在简陋,也是花了些时间才大概搞明白怎么用,下面就放出代码给大家演示下
服务端
获取授权码服务端代码示例
@RequestMapping("/authorize") public ModelAndView authorize(HttpServletRequest request) throws OAuthSystemException, OAuthProblemException, URISyntaxException { ModelAndView mav = new ModelAndView(); // 构建OAuth请求 OAuthAuthzRequest oAuthzRequest = new OAuthAuthzRequest(request); // 获取OAuth客户端Id String clientId = oAuthzRequest.getClientId(); // 校验客户端Id是否正确 if (!checkClientId(clientId)) { mav.addObject("msg", "无效的客户ID"); mav.setViewName("forward:/ljdp/oauth/authorizefail"); returnmav; }
//检查用户是否登陆和同意授权,如何还没登陆则跳转至登陆页面,然后进行授权提示 //待开发。。。
//生成授权码 String authCode = null; String responseType = oAuthzRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE); //ResponseType仅支持CODE和TOKEN if(responseType.equals(ResponseType.CODE.toString())){ OAuthIssuerImpl oAuthIssuerImpl = new OAuthIssuerImpl(new MD5Generator()); authCode = oAuthIssuerImpl.authorizationCode(); System.out.println("授权码="+authCode); }
//获取客户端重定向地址 String redirectURI = oAuthzRequest.getParam(OAuth.OAUTH_REDIRECT_URI); mav.setViewName("redirect:"+redirectURI+"?code="+authCode); returnmav; } |
获取Access Token服务端代码示例
@RequestMapping("/accesstoken") public ResponseEntity<String> accessToken(HttpServletRequest request) throws OAuthSystemException, OAuthProblemException{ //构建OAuth请求 OAuthTokenRequest tokenRequest = new OAuthTokenRequest(request); //获取OAuth客户端Id String clientId = tokenRequest.getClientId(); //校验客户端Id是否正确 if(!checkClientId(clientId)){ OAuthResponse oAuthResponse = OAuthASResponse .errorResponse(HttpServletResponse.SC_BAD_REQUEST) .setError(OAuthError.TokenResponse.INVALID_CLIENT) .setErrorDescription("无效的客户端Id") .buildJSONMessage(); System.out.println(oAuthResponse.getBody()); return new ResponseEntity<String>(oAuthResponse.getBody(), HttpStatus.valueOf(oAuthResponse.getResponseStatus())); }
//检查客户端安全KEY是否正确 if(!checkClientSecret(tokenRequest.getClientSecret())){ OAuthResponse response = OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED) .setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT) .setErrorDescription("客户端安全KEY认证不通过") .buildJSONMessage(); return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); }
//检查redirect_uri是否和认证的一致 if(!checkRedirectUri(tokenRequest.getRedirectURI())){ OAuthResponse response = OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED) .setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT) .setErrorDescription("客户端认证不通过") .buildJSONMessage(); return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); }
//验证类型,有AUTHORIZATION_CODE/PASSWORD/REFRESH_TOKEN/CLIENT_CREDENTIALS if(tokenRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(GrantType.AUTHORIZATION_CODE.toString())){ String authCode = tokenRequest.getParam(OAuth.OAUTH_CODE); if(!checkAuthCode(authCode)){ OAuthResponse response = OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST) .setError(OAuthError.TokenResponse.INVALID_GRANT) .setErrorDescription("错误的授权码") .buildJSONMessage(); return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } //生成访问令牌 OAuthIssuerImpl authIssuerImpl = new OAuthIssuerImpl(new MD5Generator()); String accessToken = authIssuerImpl.accessToken();
//生成OAuth响应 OAuthResponse response = OAuthASResponse .tokenResponse(HttpServletResponse.SC_OK) .setAccessToken(accessToken) .setExpiresIn("1000") .buildJSONMessage(); System.out.println(response.getBody()); // HttpHeaders headers = new HttpHeaders(); // headers.setContentType(MediaType.APPLICATION_JSON); return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); }
OAuthResponse response = OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST) .setError(OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE) .setErrorDescription("不支持此授权类型") .buildJSONMessage(); return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } |
用Accesstoken获取授权用户资源服务器端代码示例
@RequestMapping("/resource") @ResponseBody public AuthUserInfo resource(HttpServletRequest request, HttpServletResponse response) { // Make the OAuth Request out of this request and validate it // Specify where you expect OAuth access token (request header, body // or query string) OAuthAccessResourceRequest oauthRequest = new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);
// Get the access token String accessToken = oauthRequest.getAccessToken();
// ... validate access token
//验证通过返回用户信息 return new AuthUserInfo("test", "测试"); } |
客户端
获取accessToken代码示例
OAuthClientRequest request = OAuthClientRequest //获取accesstoken地址 .tokenLocation("http://localhost:8080/ljdp/oauth/accesstoken") //授权方式 .setGrantType(GrantType.AUTHORIZATION_CODE) //你的clientid和secret .setClientId("your-application-client-id") .setClientSecret("your-application-client-secret") //第一步重定向的uri .setRedirectURI("http://localhost:8080/ljdp/oauth/getcode") //第一步获取的认证码 .setCode("****") .buildQueryMessage();
//create OAuth client that uses custom http client under the hood OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
//Custom response classes are an easy way to deal with oauth providers that introduce modifications to //OAuth 2.0 specification OAuthJSONAccessTokenResponse oAuthResponse = oAuthClient.accessToken(request, OAuthJSONAccessTokenResponse.class);
String accessToken = oAuthResponse.getAccessToken(); Long expiresIn = oAuthResponse.getExpiresIn(); |
用accesstoken获取用户资源代码示例
OAuthClientRequest bearerClientRequest = new OAuthBearerClientRequest( "http://localhost:8080/ljdp/oauth/resource") .setAccessToken("********") .buildQueryMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
OAuthResourceResponse resourceResponse = oAuthClient.resource( bearerClientRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
System.out.println(resourceResponse.getBody()); System.out.println(resourceResponse.getResponseCode()); |
相关推荐
在"springboot OAuth2.0-demo"这个项目中,开发者已经实现了一个简单的OAuth2.0授权流程的示例。这个项目可能包含以下组件: - `AuthorizationServerConfig`:配置OAuth2.0授权服务器,定义令牌策略和范围。 - `...
这个"spring oauth2.0 例子"是一个在MyEclipse集成开发环境中创建的示例项目,用于演示如何在Spring框架中实现OAuth2.0认证和授权流程。 首先,OAuth2.0的核心概念包括客户端、资源所有者(用户)、授权服务器和...
通过深入研究 Apache Amber 的源码,开发者不仅可以理解 OAuth 2.0 协议的工作原理,还能学习到如何在实际项目中实现和定制 OAuth 2.0 服务端。这将有助于提升应用的安全性和用户体验,因为用户可以在不泄露用户名和...
Node.js 是一个基于 Chrome V8 引擎...通过研究和运行这个示例,你可以深入理解 OAuth2.0 的工作原理以及如何在 Node.js 中实现它。同时,也可以根据实际需求对示例进行扩展,比如添加更多的授权类型、令牌验证策略等。
在这个"php-oauth2.0 demo"项目中,我们将探讨如何在PHP环境中实现OAuth 2.0的基本功能。 1. **OAuth 2.0 架构** OAuth 2.0 主要有四个角色:资源所有者(Resource Owner)、客户端(Client)、认证服务器...
.NET Core 3.1 MVC框架是Microsoft开发的一个高性能...通过深入研究这个项目,开发者可以学习到OAuth 2.0的工作原理,以及如何安全地在.NET Core环境中实现这一功能,从而扩展其应用的功能,与Xero的会计数据无缝交互。
学习这个项目,你可以理解OAuth2.0协议的工作原理,掌握服务端和客户端的实现细节,同时了解如何在实际项目中安全地使用OAuth2.0进行授权登录。这对于开发涉及用户授权的Web应用或者API服务至关重要。
这个“IOS sina 腾讯 微博 OAuth2.0 授权DEMO”是一个演示如何在iOS应用中实现Sina Weibo和Tencent Weibo的OAuth2.0授权流程的实例。 首先,OAuth2.0的核心概念是授权码(Authorization Code)。当用户同意应用访问...
这个“auth2.0 安装包及资料学习”压缩包提供了多种资源,帮助开发者理解和实践 OAuth 2.0 的实现,特别强调了与 PHP 和 MySQL 的集成。 1. **OAuth 2.0 概述** OAuth 2.0 是一个开放标准,允许用户让第三方应用在...
OAuth2-Sample是一个基于OAuth2.0协议的示例项目,主要展示了如何在Java环境中实现OAuth2.0授权框架。OAuth2.0是互联网上广泛...通过研究这个示例,你可以更好地掌握OAuth2.0的工作原理,以及如何在实际项目中实现它。
通过分析和学习这些代码,开发者可以更好地理解OAuth 2.0的工作原理,掌握如何在自己的应用中安全、高效地实施OAuth 2.0授权。这有助于提升应用程序的安全性,保护用户数据,并为用户提供无缝的第三方服务接入体验。
消费者可以通过 OAuth 2.0 协议获取 JWT 访问令牌。 访问令牌被发送到 Web API 以对用户进行身份验证。 Web API 使用 java 来验证访问令牌。 有关协议在此方案和其他方案中的工作方式的详细信息,请参阅。 有关...
- **章节7**:深入讨论OAuth2.0的各种实现细节及可能存在的安全风险。 - **主题**:覆盖最佳实践、常见漏洞(如令牌泄露、重放攻击)及其防范措施。 - **案例分析**:通过具体案例讲解如何避免这些安全问题。 ...
1. **文档**:包含详细的开发指南或教程,解释OAuth2.0的工作原理和流程。这通常会包括客户端注册、获取client_id和client_secret,以及获取access_token的过程。 - **授权流程**:OAuth2.0分为几个关键步骤:资源...
`oauth2sample`是这样一个库,它专注于OAuth 2.0协议的实现,这是一种广泛使用的授权框架,用于安全地获取和使用用户的数据。`oauth2sample-0.1.tar.gz`是一个包含该库源代码的压缩包文件,通过解压可以获取到其内部...
在这个"oAuthWithSpringJava"项目中,开发者可能已经创建了一个使用Spring Security和oAuth2.0的示例应用,以演示如何在Java应用程序中实现授权功能。Spring Security是Spring生态系统的一个模块,专门用于处理应用...
- 文件"aaronpk-oauth.net-2e34467"可能是一个开源项目或者示例,用于演示如何在Java中实现OAuth 2.0的客户端或服务器端功能。 - 使用这个项目,开发者可以学习如何设置OAuth 2.0的授权流程,创建自定义授权端点,...
在这个“platzi-autenticacion:OAuth认证课程”中,我们将深入探讨OAuth 2.0协议的工作原理,以及如何在实际的JavaScript项目中实现它。 OAuth 2.0 主要包含四个角色:资源所有者、资源服务器、客户端和授权服务器...
"resource-server:演示OAuth2" 是一个基于Spring Security的项目,它展示了如何配置和实现OAuth 2.0 的资源服务器。 首先,OAuth 2.0 的核心概念包括客户端、用户、资源所有者和授权服务器。在这个项目中,...
"oauthDemo代码"是一个示例项目,用于演示OAuth的实现过程。这个项目可能包含了以下关键知识点: 1. OAuth流程:OAuth通常涉及四个角色:资源所有者(用户)、客户端(第三方应用)、资源服务器(服务提供者)和...