- 浏览: 517753 次
- 性别:
- 来自: 无锡
文章分类
最新评论
-
鬼一天:
代码有问题,没有考虑负数的情况。
根据经纬度和半径计算经纬度范围 -
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 1770开始尝试过rvm,但因为 ... -
Rails 多表关联查询指定字段的方法
2011-03-04 15:25 5581Rails中都是返回的单个模型的对象,怎么返回多个表中的指定字 ... -
新浪微博oauth简易客户端ruby实现
2010-12-29 11:07 4131前后花了近一个星期,中间就sha1的加密就纠结了几天。。。 ... -
使用monit工具对thin进程的监控
2010-08-27 11:07 2441monit可以对服务器进程进行监控,如果发现服务器进程挂掉,则 ... -
最近服务器总是出现504错误,又想不到是什么原因造成的,郁闷!!
2010-08-22 13:33 6553服务器在机房,为了能方便查看日志,就配置了一个路径可以直 ... -
ActiveRecord学习之多数据库访问和事务控制
2010-07-03 16:37 2900多数据库的访问 目的:在同一个应用中访问不同数据库,以 ... -
ActiveRecord学习(二)
2010-06-20 16:15 1395单表继承 官方文档:ht ... -
Rails部分辅助方法
2010-06-14 18:43 7623AssetTagHelper 官方链接:http://ap ... -
Rails命名约定
2010-06-14 15:41 1556模型命名规则 数据库表名:hello_texts, ... -
ActiveRecord学习
2010-06-13 14:21 17559ActiveRecord是Rails进行数据库操作的核心组件。 ... -
Rails学习之路由设置(URI映射)
2010-06-12 15:34 3486URL的映射规则,在config/routes.rb文件中。这 ... -
Rails学习之控制器
2010-06-12 13:46 5475控制器简单介绍 一个简单的控制器中的例子 class Si ... -
Rails简单文件上传
2010-06-10 20:03 1783RMagick和ruby-debug-ide还是没有安装成功, ... -
Rails的中文乱码问题
2010-06-09 14:19 8895乱码情况一:netbeas控制 ... -
Rails简单练习
2010-06-08 21:24 1701对Rails的一个简单的练习 一个学生和教师的CRUD,以及 ... -
StatementInvalid: Mysql::Error: query: not connected解决方法
2010-06-07 16:21 2836今天学习rails,在使用scoffold建立一张表的CRUD ...
相关推荐
新浪微博OAuth 验证
OAuth2认证资源 实现微博的
RT,使用WebView实现新浪微博Oauth2.0认证,非截取html代码获取验证码 界面跳转无副作用
Oauth 2.0 新浪微博 腾讯微博 实现2个微博的授权与发布一条微博。
这是我使用Oauth2.0实现新浪微博客户端(C#),里面有我申请的AppKey, AppSecret, 公开给大家尽情使用
新浪微博OAuth授权的Java实现.pdf
本例子自己学习最近刚刚接触新浪微博的demo 逻辑不是很好 仅供需要的人参考 WeiBo1.0 没有用线程访问网络 4.0以上不能使用 WeiBo2.0s1 添加了线程访问网络 4.0测试能够...微博是通过OAuth2验证的方式 而非是OAuth方式
OAUTH1.0腾讯登录与新浪微博登录 里面包括全代码,
一个完整的新浪微博客户端android版OAuth认证 开发我的新浪微博客户端-大图浏览以及保存篇 开发我的新浪微博客户端-阅读微博功能篇 开发我的新浪微博客户端-阅读微博UI篇 开发我的新浪微博客户端-用户首页面功能篇 ...
帮助新手学习OAuth的一个很好的示例 http://blog.csdn.net/koastal/article/details/50282509
实现新浪微博的OAuth2.0认证登陆,有自己找的资源,以及一些对自己帮助很大的网页,由于新浪微博不支持OAuth1.0了,所以把项目里的新浪微博登陆改为OAuth2.0了
易语言新浪微博开源oauth版源码例程程序结合易语言扩展界面支持库和WEB客户2.1版,实现新浪微博的oauth认证登录,及浏览、发布新浪微博信息。 本易语言例程还使用到易语言多线程支持库,易语言应用接口支持库,超文本...
最新的《Android应用开发实战》源码版本,基于Oauth2验证的功能。
4. OAuth2.0 授权 5. 归档存储数据 6. AFN工具类封装 7. 网络请求业务类封装 8. menu菜单 9. MVVM 创建首页cell 10.特殊字段的点击 10. FMDB存储数据 11. 发送微博界面 12.自定义表情键盘,并发送表情 13....
3./class/下,文件名中含有If的文件,定义的是接口.总计3个接口文件:各个网站的api访问路径...5.实例中2个网站(新浪微博和腾讯微博)的OAuth已经实现,并且通过验证。本例中的OAuth客户端来源于新浪微博OAuth认证SDK。
易语言源码易语言新浪微博开源oauth版.rar 易语言源码易语言新浪微博开源oauth版.rar 易语言源码易语言新浪微博开源oauth版.rar 易语言源码易语言新浪微博开源oauth版.rar 易语言源码易语言新浪微博开源oauth版....
教程名称:Android平台新浪微博开发实战视频教程(10集)教程目录:【】Android项目_-6(上)【】Android项目_新浪微博-4(上)【】Android项目_新浪微博Android客户端开发ppt【】Android项目_新浪微博OAuth认证-4(下)...
本文档使用C#语言开发,MVC框架调用新浪微博第三方登录OAuth2.0接口。 详细介绍相关开发步骤信息。
最近开放平台非常火,各大互联网公司都纷纷推出各自的开放平台,随之流行的 OpenID, OAuth 则成为认证和授权的主要技术。本文将以登陆新浪微博获得授权取得用户数据作为示例简单研究 OAuth 的使用
新浪微博OAuth授权的Java实现,这篇文章中,我想用比较通俗的语言来解释OAuth协议。