- 浏览: 522406 次
- 性别:
- 来自: 无锡
文章分类
最新评论
-
鬼一天:
代码有问题,没有考虑负数的情况。
根据经纬度和半径计算经纬度范围 -
Tair:
...
通过反射把map中的属性赋值到实体类bean对象中 -
springmvc_springjpa:
spring mvc demo教程源代码下载,地址:http: ...
Spring3.0 MVC的初次尝试 -
酷的飞上天空:
haiyinlong 写道private File value ...
使用HttpUrlConnection进行post请求上传文件 -
lliiqiang:
分析很难,好的规则持久,靠某个方法条件局限不能证明长久
ruby的基本类型
前段时间用ruby实现了新浪微博的简易Oauth的客户端,对aouth协议有了一个大概的了解。
完成服务器端的实现,纯属自己一个的加深学习aouth的想法,嘿嘿. 验证支持basic,oauth,xauth
接收下用到的controller
OauthController 负责对用户aouth验证和发放accessToken
Oauth_base_controller 所有需要aouth验证的controller的父类,对子类的所有方法进行权限验证
一个帮助类
OauthUtil 负责字符串的加密和拼接
OauthController提供三个对外方法:
request_token
authorize
access_token
具体方法含义,对应oauth验证的每个url。
具体代码如下
# coding: utf-8 # HTTP 400 Bad Request # o Unsupported parameter # o Unsupported signature method # o Missing required parameter # o Duplicated OAuth Protocol Parameter # HTTP 401 Unauthorized # o Invalid Consumer Key # o Invalid / expired Token # o Invalid signature # o Invalid / used nonce class OauthController < Oauth_base_controller TEST_APP_KEY = "123456" TEST_APP_SECRET = "654321" TEST_OAUTH_TOKEN = "QWERTY" TEST_OAUTH_TOKEN_SECRET ="YUIOP" TEST_OAUTH_VERIFIER = "ASDFG" TEST_ACCESS_TOKEN = "HJKLG" TEST_ACCESS_TOKEN_SECRET = "ZXCVB" protect_from_forgery :except => [:request_token,:authorize,:access_token] skip_before_filter :auth def request_token oauth_signature = params["oauth_signature"] puts "=======================params======================",params.inspect render :json=>%({"error":400,"detail":"need signature"}),:status => 400,:callback=>params[:callback] and return if oauth_signature.blank? oauth_signature = CGI::unescape oauth_signature oauth_params = { :oauth_consumer_key => params["oauth_consumer_key"], :oauth_timestamp => params["oauth_timestamp"], :oauth_nonce => params["oauth_nonce"], :oauth_version => params["oauth_version"] || "1.0", :oauth_signature_method => "HMAC-SHA1" } oauth_params[:oauth_callback] = params["oauth_callback"] if params["oauth_callback"] oauth_params[:oauth_body_hash] = params["oauth_body_hash"] if params["oauth_body_hash"] httpmethod = request.method.to_s base_uri = "http://#{request.headers["HTTP_HOST"]}/oauth/request_token" key = "#{TEST_APP_SECRET}&" create_base_string = OauthUtil.create_oauth_signature(httpmethod.upcase, base_uri, oauth_params, key) puts "===============oauth_signature,create_base_string",oauth_signature,create_base_string render :json=>%({"error":401,"detail":"Invalid signature"}),:status => 401,:callback=>params[:callback] and return if create_base_string != oauth_signature render :text => "oauth_token=#{TEST_OAUTH_TOKEN}&oauth_token_secret=#{TEST_OAUTH_TOKEN_SECRET}" if params["oauth_callback"].nil? render :text => "oauth_token=#{TEST_OAUTH_TOKEN}&oauth_token_secret=#{TEST_OAUTH_TOKEN_SECRET}&oauth_callback_confirmed=true" if params["oauth_callback"] end def authorize @token = params[:oauth_token] @oauth_callback = params[:oauth_callback] render :text => "no token error" and return if @token.blank? if request.get? @name = "测试应用" render :action => "authorize" return end if request.post? username = params[:username] password = params[:password] if username.nil? || password.nil? || username != "test" || password !="test" flash[:notice] = "用户名或密码错误" render :action => "authorize" return else render :text => "授权已完成" and return if params[:oauth_callback].blank? callback = OauthUtil.callback_url(CGI::unescape(params[:oauth_callback]), @token, TEST_OAUTH_VERIFIER) redirect_to callback return end end return :text=>"" end def access_token oauth_signature = params["oauth_signature"] render :json=>%({"error":400,"detail":"need signature"}),:status => 400,:callback=>params[:callback] and return if oauth_signature.blank? oauth_signature = CGI::unescape oauth_signature puts "=======================params======================",params.inspect ## for oauth oauth_params = { :oauth_consumer_key => params["oauth_consumer_key"], :oauth_token => params["oauth_token"], :oauth_timestamp => params["oauth_timestamp"], :oauth_nonce => params["oauth_nonce"], :oauth_version => params["oauth_version"] || "1.0", :oauth_signature_method => "HMAC-SHA1" } ## for xauth oauth_params = { :x_auth_username => params["x_auth_username"], :x_auth_password => params["x_auth_password"], :x_auth_mode => "client_auth", :oauth_consumer_key => params["oauth_consumer_key"], :oauth_timestamp => params["oauth_timestamp"], :oauth_nonce => params["oauth_nonce"], :oauth_version => "1.0", :oauth_signature_method => "HMAC-SHA1" } if xauth? render :json=>%({"error":403,"detail":"unsupport XAuth"}),:status => 403,:callback=>params[:callback] and return if xauth? render :json=>%({"error":401,"detail":"Invalid signature"}),:status => 401,:callback=>params[:callback] and return if params["x_auth_username"] != "test" || params["x_auth_password"] != "test" oauth_params[:oauth_body_hash] = params["oauth_body_hash"] if params["oauth_body_hash"] oauth_params[:oauth_verifier] = params["oauth_verifier"] if params["oauth_verifier"] httpmethod = request.method.to_s base_uri = "http://#{request.headers["HTTP_HOST"]}/oauth/access_token" key = "#{TEST_APP_SECRET}&#{TEST_OAUTH_TOKEN_SECRET}" key = "#{TEST_APP_SECRET}&" if xauth? ## for xauth create_base_string = OauthUtil.create_oauth_signature(httpmethod.upcase, base_uri, oauth_params, key) puts "===============oauth_signature,create_base_string",oauth_signature,create_base_string render :json=>%({"error":401,"detail":"Invalid signature "}),:status => 401,:callback=>params[:callback] and return if create_base_string != oauth_signature render :text => "oauth_token=#{TEST_ACCESS_TOKEN}&oauth_token_secret=#{TEST_ACCESS_TOKEN_SECRET}" end def xauth? params["x_auth_username"] || params["x_auth_password"] end end
其中OauthUtil类源码如下
# coding: utf-8 require "uri" class OauthUtil class << self ## 生成base_string 字符串 def base_string(httpmethod,base_uri,request_params) base_str = httpmethod + "&" + CGI::escape(base_uri) + "&" base_str += request_params.to_a.sort{|a,b| a[0].to_s <=> b[0].to_s}.map{|param| CGI::escape(param[0].to_s) + "%3D"+ CGI::escape(param[1].to_s)}.join("%26") puts "===========base_string===========",base_str base_str end ## see http://stackoverflow.com/questions/1959486/digest-hmac-is-part-of-ruby-standard-lib def digest(value,key) puts "===========digest_key===========",key signature = Base64.encode64 OpenSSL::HMAC.digest("SHA1", key, value) puts "===========signature===========",signature.strip signature.strip end def create_oauth_signature(httpmethod,base_uri,request_params,key) create_base_string = base_string httpmethod,base_uri,request_params digest create_base_string,key end def callback_url(url,oauth_token,oauth_verifier) begin uri = URI::parse(url) rescue Exception return "" end query_string = uri.query query_string = "&#{query_string}" if query_string "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}?oauth_token=#{oauth_token}&oauth_verifier=#{oauth_verifier}#{query_string}" end end end
涉及到的erb页面authorize.html.erb页面代码如下
是否要授权<%=@name%>应用,使用你在本网站的部分功能? <form action="/oauth/authorize" method="post"> <input type="hidden" value="<%=@token%>" name="oauth_token"/> <input type="hidden" value="<%=@oauth_callback%>" name="oauth_callback"/> 账号:<input type="text" name="username"></input><br /> 密码:<input type="password" name="password"></input><br /> <input type="submit" value="授权"/> </form> 如果不想授权,请关闭此页面。 <p><%=flash[:notice]%></p>
Oauth_base_controller 主要方法为auth,为子类提供验证,具体源码如下:
# coding: utf-8 class Oauth_base_controller < ApplicationController before_filter :handle_headers_oauth_string before_filter :auth ## 进行验证 def auth authenticate = request.headers["AUTHORIZATION"] || request.headers["HTTP_AUTHORIZATION"] if authenticate.blank? auth_oauth else authenticate_method = authenticate[0,5] authenticate_body = authenticate[5,authenticate.size - 5] case authenticate_method when "Basic" @name_pwd = Base64.decode64(authenticate_body.strip) puts "name_pwd",@name_pwd render :json=>%({"error":401,"detail":"authenticate format error"}),:status => "401",:callback=>params[:callback] and return false if @name_pwd.split(":").size != 2 auth_basic else "OAuth" auth_oauth end end end ## 要移除的相关非oauth计算签名参数 def except_other_params except_params "realm",params["realm"] except_params "oauth_signature",params["oauth_signature"] except_params "action",params["action"] except_params "controller",params["controller"] end ## 将非oauth计算签名所需参数移动到except_params中去 def except_params(key,value) @except_params = {} if @except_params.nil? @except_params[key] = value params.delete key.to_s params.delete key.to_sym end private ## 进行 Basic 验证 def auth_basic username = @name_pwd.split(":")[0] password = @name_pwd.split(":")[1] render :json=>%({"error":401,"detail":"authenticate fail"}),:status => "401",:callback=>params[:callback] and return false if username != "test" || password != "test" end ## 进行oauth 验证 def auth_oauth params["oauth_version"] ||= "1.0" puts "=======================params======================",params.inspect oauth_signature = params["oauth_signature"] render :json=>%({"error":400,"detail":"need signature"}),:status => "400",:callback=>params[:callback] and return if oauth_signature.blank? oauth_signature = CGI::unescape oauth_signature except_other_params httpmethod = request.method.to_s base_uri = "http://#{request.headers["HTTP_HOST"]}#{request.path}" key = "#{app_secret_by_oauth_consumer_key params["oauth_consumer_key"]}&#{token_secret_by_access_token params["oauth_token"]}" create_base_string = OauthUtil.create_oauth_signature(httpmethod.upcase, base_uri, params, key) puts "===============oauth_signature,create_base_string",oauth_signature,create_base_string render :json=>%({"error":401,"detail":"Invalid signature"}),:status => "401",:callback=>params[:callback] and return if create_base_string != oauth_signature end ## 查找app_key 对应的secret def app_secret_by_oauth_consumer_key(app_key) "654321" end ## 查找access_token 对应的secret def token_secret_by_access_token(access_token) "ZXCVB" end ## 整理header里面的oauth 的参数到params里面去 def handle_headers_oauth_string authenticate = request.headers["AUTHORIZATION"] || request.headers["HTTP_AUTHORIZATION"] return true if authenticate.blank? oauth_method = authenticate[0,5] return true if oauth_method == "Basic" render :json=>%({"error":401,"detail":"http_headers content error"}),:status => "401",:callback=>params[:callback] and return false if oauth_method != "OAuth" oauth_body = authenticate[5,authenticate.size - 5] oauth_body.split(",").each do |header_param| next if header_param.split("=").size != 2 k = header_param.split("=")[0].strip v = header_param.split("=")[1].strip.gsub(/\"/,"") params[k] = v end end end
使用方式为,继承Oauth_base_controller,然后子类中的所有方法则都要进行验证后才能访问,如:
# coding: utf-8 class OauthTestController < Oauth_base_controller def index puts "=======================",request.headers.inspect render :text => request.headers.inspect end end
当访问这个index方法的时候,会进行oauth或basic验证,如果通过则返回客户端的请求头字符串,否则返回相应的验证失败代码
评论
2 楼
酷的飞上天空
2013-01-13
zhangyuxiu 写道
请教下:
1. 获取APP_KEY及APP_SECRET属于服务器端的设计范围么?
2. 上述实现的服务器端应该等同于新浪微博开放平台吧?那么测试用的APP,APP_SECRET是如何获得的啊?
1. 获取APP_KEY及APP_SECRET属于服务器端的设计范围么?
2. 上述实现的服务器端应该等同于新浪微博开放平台吧?那么测试用的APP,APP_SECRET是如何获得的啊?
回答一:
APP_KEY及APP_SECRET的发放和验证是分开的。发放端一般是一个特定的应用管理平台,可以让用户自己提交应用然后平台自动生成这两个,也可能是管理员手动建立。
回答而:
上述实现只是自己研究新浪oauth客户端验证时,兴趣上来想自己实现下服务器,只能说简易实现,实际情况肯定要复杂的多的。
另:现在新浪已经换成oauth2了。
1 楼
zhangyuxiu
2012-12-25
请教下:
1. 获取APP_KEY及APP_SECRET属于服务器端的设计范围么?
2. 上述实现的服务器端应该等同于新浪微博开放平台吧?那么测试用的APP,APP_SECRET是如何获得的啊?
1. 获取APP_KEY及APP_SECRET属于服务器端的设计范围么?
2. 上述实现的服务器端应该等同于新浪微博开放平台吧?那么测试用的APP,APP_SECRET是如何获得的啊?
发表评论
-
rails部署ree+nginx+passenger
2011-04-16 22:09 1808开始尝试过rvm,但因为 ... -
Rails 多表关联查询指定字段的方法
2011-03-04 15:25 5627Rails中都是返回的单个模型的对象,怎么返回多个表中的指定字 ... -
新浪微博oauth简易客户端ruby实现
2010-12-29 11:07 4178前后花了近一个星期,中间就sha1的加密就纠结了几天。。。 ... -
使用monit工具对thin进程的监控
2010-08-27 11:07 2506monit可以对服务器进程进行监控,如果发现服务器进程挂掉,则 ... -
最近服务器总是出现504错误,又想不到是什么原因造成的,郁闷!!
2010-08-22 13:33 6610服务器在机房,为了能方便查看日志,就配置了一个路径可以直 ... -
ActiveRecord学习之多数据库访问和事务控制
2010-07-03 16:37 2944多数据库的访问 目的:在同一个应用中访问不同数据库,以 ... -
ActiveRecord学习(二)
2010-06-20 16:15 1436单表继承 官方文档:ht ... -
Rails部分辅助方法
2010-06-14 18:43 7668AssetTagHelper 官方链接:http://ap ... -
Rails命名约定
2010-06-14 15:41 1584模型命名规则 数据库表名:hello_texts, ... -
ActiveRecord学习
2010-06-13 14:21 17602ActiveRecord是Rails进行数据库操作的核心组件。 ... -
Rails学习之路由设置(URI映射)
2010-06-12 15:34 3527URL的映射规则,在config/routes.rb文件中。这 ... -
Rails学习之控制器
2010-06-12 13:46 5540控制器简单介绍 一个简单的控制器中的例子 class Si ... -
Rails简单文件上传
2010-06-10 20:03 1823RMagick和ruby-debug-ide还是没有安装成功, ... -
Rails的中文乱码问题
2010-06-09 14:19 8974乱码情况一:netbeas控制 ... -
Rails简单练习
2010-06-08 21:24 1744对Rails的一个简单的练习 一个学生和教师的CRUD,以及 ... -
StatementInvalid: Mysql::Error: query: not connected解决方法
2010-06-07 16:21 2881今天学习rails,在使用scoffold建立一张表的CRUD ...
相关推荐
新浪微博采用OAuth协议进行第三方应用授权,XWeibo在实现用户授权登录功能时,也需要理解并应用OAuth协议,确保安全地获取和使用用户的微博账户权限。 6. **模板引擎** 为了提高视图层的复用性和可维护性,XWeibo...
该压缩包文件包含的是一个仿新浪微博的网站源代码,它是一个基于Web开发的项目,用于构建类似新浪微博的社交网络平台。下面将详细解释这个项目可能涉及的一些关键知识点和技术。 1. **网站架构**:仿新浪微博的网站...
7. **登录与授权**: 实现微博登录功能,需要集成新浪的OAuth2.0授权协议,通过SDK进行用户验证和授权,获取访问令牌。 8. **推送通知**: 对于实时性要求高的社交应用,可以集成Firebase Cloud Messaging (FCM) 来...
微博作为中国主要的社交媒体平台之一,其开放API接口允许开发者通过OAuth验证机制来获取用户的授权,以便在第三方应用中实现微博的功能,如发布微博、读取用户信息等。OAuth验证是一种广泛使用的授权协议,它使得...
5. 社交媒体集成:为了实现微博分享,需要使用新浪开放平台提供的SDK。首先,开发者需要注册并获取App Key和App Secret。然后,将SDK集成到项目中,通过OAuth2.0授权协议获取用户授权,调用SDK提供的接口发送分享...
C#新浪微博验证程序是一款基于C#编程语言开发的应用,主要用于实现微博用户在第三方网站上的身份验证。这个程序的核心功能是利用OAuth授权协议,允许用户使用其新浪微博账号登录到非新浪的网站,从而提高用户体验,...
这个“OAuth2.0新浪微博简单示例”是为初学者设计的,旨在帮助理解OAuth2.0的工作原理及其在实际应用中的实现方式,特别是与新浪微博的集成。 首先,我们来深入了解一下OAuth2.0的核心概念: 1. **客户端(Client...
新浪微博OAuth授权的Java实现 一、 OAuth协议简介 OAuth协议是一种广泛使用的授权协议,使用户不需要直接向第三方应用提供用户名及密码,且使一个账户在多个网站中使用成为可能。OAuth协议的细节描述可参考其官方...
【Android 仿新浪微博】项目是基于Android平台的一个开源项目,其目标是实现一个类似新浪微博的应用。这个项目对于学习Android开发,尤其是社交应用的构建,提供了丰富的实践参考。 首先,项目的核心在于用户界面...
在Android平台上,开发一款仿新浪微博客户端是一项挑战性的任务,它涉及到多个关键的技术点,包括UI设计、网络请求、数据解析、缓存策略、用户登录授权、动态加载与刷新、社交功能实现等。以下是对这个项目中涉及的...
OAuth 1.0的核心概念包括三个主要角色:资源所有者(用户)、客户端(第三方应用)和认证服务器(腾讯或新浪微博)。当用户想要使用第三方应用访问其在社交媒体平台上的数据时,OAuth 1.0提供了一种授权机制。 1. *...
【标题】:“新浪微博API OAuth认证”是一个关于使用OAuth授权机制与新浪微博API进行交互的技术主题。OAuth是一种开放标准,允许用户提供一个令牌,而不是用户名和密码来访问他们存储在特定服务提供者的数据。在微博...
在本例中,我们将讨论如何使用C#来实现一个基于OAuth2.0的新浪微博客户端。 **C#** 是一种面向对象的编程语言,由微软开发,主要用于.NET Framework。在C#中,我们可以利用HTTP请求库如HttpClient或Flurl来发送网络...
在实现微博的OAuth2认证时,我们通常会经历以下步骤: 1. **注册应用**:首先,开发者需要在微博开放平台注册自己的应用,获取到应用的ID(Client ID)和密钥(Client Secret)。这两个值在后续的认证过程中至关...
总之,这篇关于“新浪微博登录 sina”的博文和提供的源码文件“sina_oauth”,对于想要在自己的应用中实现微博登录功能的开发者来说,是一个宝贵的资源,可以帮助他们快速理解和实践OAuth授权过程,从而提高开发效率...
这篇文档将详细介绍如何使用OAuth2.0协议实现新浪微博的登录功能。OAuth2.0是目前广泛采用的授权框架,它允许第三方应用在用户许可的情况下访问其存储在特定服务提供商(如新浪微博)上的数据,而无需获取用户的...
本教程将详细阐述如何使用C#语言和MVC框架实现新浪微博的OAuth2.0登录流程。 首先,我们需要理解OAuth2.0的基本流程。OAuth2.0的核心是四类角色:资源所有者(用户)、资源服务器(如新浪微博)、客户端(你的应用...
【标题】"仿新浪微博客户端"涉及的是一款针对Android平台开发的应用程序,旨在模仿新浪微博的功能和用户体验。这样的项目对于初学者来说是一个很好的实践案例,因为它涵盖了移动应用开发中的多个关键技术和设计原则...
在这个场景下,我们关注的是一个基于ThinkPHP框架实现的新浪微博用户同步登录功能的代码实例。这个功能允许用户使用他们的新浪微博账号直接登录到你的网站,为用户提供便利,同时也可以帮助开发者吸引并保留更多用户...
【标题】:“仿新浪微博”项目实现详解 在移动应用开发领域,模仿知名社交网络平台如新浪微博的功能和用户体验是一种常见的学习和实践方式。本项目“仿新浪微博”旨在通过模仿微博的关键特性,帮助开发者深入理解...