You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

13 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. OpenIdAuthentication
  2. ====================
  3. Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:
  4. gem install ruby-openid
  5. To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb
  6. from that gem.
  7. The specification used is http://openid.net/specs/openid-authentication-2_0.html.
  8. Prerequisites
  9. =============
  10. OpenID authentication uses the session, so be sure that you haven't turned that off.
  11. Alternatively, you can use the file-based store, which just relies on on tmp/openids being present in RAILS_ROOT. But be aware that this store only works if you have a single application server. And it's not safe to use across NFS. It's recommended that you use the database store if at all possible. To use the file-based store, you'll also have to add this line to your config/environment.rb:
  12. OpenIdAuthentication.store = :file
  13. This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
  14. If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
  15. The plugin also expects to find a root_url method that points to the home page of your site. You can accomplish this by using a root route in config/routes.rb:
  16. map.root :controller => 'articles'
  17. This plugin relies on Rails Edge revision 6317 or newer.
  18. Example
  19. =======
  20. This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add
  21. salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
  22. not a destination.
  23. Note that the User model referenced in the simple example below has an 'identity_url' attribute. You will want to add the same or similar field to whatever
  24. model you are using for authentication.
  25. Also of note is the following code block used in the example below:
  26. authenticate_with_open_id do |result, identity_url|
  27. ...
  28. end
  29. In the above code block, 'identity_url' will need to match user.identity_url exactly. 'identity_url' will be a string in the form of 'http://example.com' -
  30. If you are storing just 'example.com' with your user, the lookup will fail.
  31. There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs.
  32. OpenIdAuthentication.normalize_url(user.identity_url)
  33. The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/'
  34. It will also raise an InvalidOpenId exception if the URL is determined to not be valid.
  35. Use the above code in your User model and validate OpenID URLs before saving them.
  36. config/routes.rb
  37. map.root :controller => 'articles'
  38. map.resource :session
  39. app/views/sessions/new.erb
  40. <% form_tag(session_url) do %>
  41. <p>
  42. <label for="name">Username:</label>
  43. <%= text_field_tag "name" %>
  44. </p>
  45. <p>
  46. <label for="password">Password:</label>
  47. <%= password_field_tag %>
  48. </p>
  49. <p>
  50. ...or use:
  51. </p>
  52. <p>
  53. <label for="openid_identifier">OpenID:</label>
  54. <%= text_field_tag "openid_identifier" %>
  55. </p>
  56. <p>
  57. <%= submit_tag 'Sign in', :disable_with => "Signing in&hellip;" %>
  58. </p>
  59. <% end %>
  60. app/controllers/sessions_controller.rb
  61. class SessionsController < ApplicationController
  62. def create
  63. if using_open_id?
  64. open_id_authentication
  65. else
  66. password_authentication(params[:name], params[:password])
  67. end
  68. end
  69. protected
  70. def password_authentication(name, password)
  71. if @current_user = @account.users.authenticate(params[:name], params[:password])
  72. successful_login
  73. else
  74. failed_login "Sorry, that username/password doesn't work"
  75. end
  76. end
  77. def open_id_authentication
  78. authenticate_with_open_id do |result, identity_url|
  79. if result.successful?
  80. if @current_user = @account.users.find_by_identity_url(identity_url)
  81. successful_login
  82. else
  83. failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
  84. end
  85. else
  86. failed_login result.message
  87. end
  88. end
  89. end
  90. private
  91. def successful_login
  92. session[:user_id] = @current_user.id
  93. redirect_to(root_url)
  94. end
  95. def failed_login(message)
  96. flash[:error] = message
  97. redirect_to(new_session_url)
  98. end
  99. end
  100. If you're fine with the result messages above and don't need individual logic on a per-failure basis,
  101. you can collapse the case into a mere boolean:
  102. def open_id_authentication
  103. authenticate_with_open_id do |result, identity_url|
  104. if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
  105. successful_login
  106. else
  107. failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
  108. end
  109. end
  110. end
  111. Simple Registration OpenID Extension
  112. ====================================
  113. Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension
  114. You can support it in your app by changing #open_id_authentication
  115. def open_id_authentication(identity_url)
  116. # Pass optional :required and :optional keys to specify what sreg fields you want.
  117. # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
  118. authenticate_with_open_id(identity_url,
  119. :required => [ :nickname, :email ],
  120. :optional => :fullname) do |result, identity_url, registration|
  121. case result.status
  122. when :missing
  123. failed_login "Sorry, the OpenID server couldn't be found"
  124. when :invalid
  125. failed_login "Sorry, but this does not appear to be a valid OpenID"
  126. when :canceled
  127. failed_login "OpenID verification was canceled"
  128. when :failed
  129. failed_login "Sorry, the OpenID verification failed"
  130. when :successful
  131. if @current_user = @account.users.find_by_identity_url(identity_url)
  132. assign_registration_attributes!(registration)
  133. if current_user.save
  134. successful_login
  135. else
  136. failed_login "Your OpenID profile registration failed: " +
  137. @current_user.errors.full_messages.to_sentence
  138. end
  139. else
  140. failed_login "Sorry, no user by that identity URL exists"
  141. end
  142. end
  143. end
  144. end
  145. # registration is a hash containing the valid sreg keys given above
  146. # use this to map them to fields of your user model
  147. def assign_registration_attributes!(registration)
  148. model_to_registration_mapping.each do |model_attribute, registration_attribute|
  149. unless registration[registration_attribute].blank?
  150. @current_user.send("#{model_attribute}=", registration[registration_attribute])
  151. end
  152. end
  153. end
  154. def model_to_registration_mapping
  155. { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
  156. end
  157. Attribute Exchange OpenID Extension
  158. ===================================
  159. Some OpenID providers also support the OpenID AX (attribute exchange) protocol for exchanging identity information between endpoints. See more: http://openid.net/specs/openid-attribute-exchange-1_0.html
  160. Accessing AX data is very similar to the Simple Registration process, described above -- just add the URI identifier for the AX field to your :optional or :required parameters. For example:
  161. authenticate_with_open_id(identity_url,
  162. :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration|
  163. This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate'
  164. Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license

软件技术创新是当今国家整体创新能力的重要基础和发展引擎。近年来,大众参与的软件创新与创业活动已经成为网络时代软件开发和应用的新形态,正在快速改变着全球软件创新模式和软件产业格局。 ...