技术开发 频道

为.NET网站增加OpenID登录方式

  【IT168技术】OpenID在国外很流行. 在国内就不怎么样了.. 很多网站,论坛都不支持. 经常在网上逛的人,几乎都要注册很多帐号,记很多密码. 或者是帐号和密码都设定一样.呵. 我在想,如果国内大量的论坛都支持OpenID登录,那么,将会多爽!

  不了解OpenID的朋友可以看中文,或英文http://www.openid.net 的介绍.

  本人最近做的一个网站( http://www.86e0.com ) 有用到OpenID的登录(当然还有其它的登录方式,慢慢会说到). 一开始我也是狂找资料, 中文的,英文的都找过了.可惜的是,资料少得很. 下面总结一些经验和分享一些代码.

  .NET下使用OpenID,首先要去下载一个第三方组件:dotnetopenauth. 网址为: http://www.dotnetopenauth.net/

  压缩包里会有示例. 由于我的项目是用Asp.NET MVC2,所以我直接看OpenIdRelyingPartyMvc 这个示例. 示例是Asp.net MVC1.0版的.很快我们就可以找出他的关键代码:

  Action为:

view sourceprint?01 [ValidateInput(false)]

  
02 public ActionResult Authenticate(string returnUrl) {

  
03 var response = openid.GetResponse();

  
04 if (response == null) {

  
05 // Stage 2: user submitting Identifier

  
06 Identifier id;

  
07 if (Identifier.TryParse(Request.Form["openid_identifier"], out id)) {

  
08 try {

  
09 return openid.CreateRequest(Request.Form["openid_identifier"]).RedirectingResponse.AsActionResult();

  
10 } catch (ProtocolException ex) {

  
11 ViewData["Message"] = ex.Message;

  
12 return View("Login");

  
13 }

  
14 } else {

  
15 ViewData["Message"] = "Invalid identifier";

  
16 return View("Login");

  
17 }

  
18 } else {

  
19 // Stage 3: OpenID Provider sending assertion response

  
20 switch (response.Status) {

  
21 case AuthenticationStatus.Authenticated:

  
22 Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay;

  
23 FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);

  
24 if (!string.IsNullOrEmpty(returnUrl)) {

  
25 return Redirect(returnUrl);

  
26 } else {

  
27 return RedirectToAction("Index", "Home");

  
28 }

  
29 case AuthenticationStatus.Canceled:

  
30 ViewData["Message"] = "Canceled at provider";

  
31 return View("Login");

  
32 case AuthenticationStatus.Failed:

  
33 ViewData["Message"] = response.Exception.Message;

  
34 return View("Login");

  
35 }

  
36 }

  
37 return new EmptyResult();

  
38 }

  
39 }

    最后在HomeController 的Index Action(就是主页)增加 X-XRDS-Location 的Header. Xrds Action是输出上面的Xrds View.如下: 其中请注意xrds的地址. 代码如下.

view sourceprint?01 public class HomeController : Controller {

  
02 public ActionResult Index() {

  
03 Response.AppendHeader(

  
04 "X-XRDS-Location",

  
05 new Uri(Request.Url, Response.ApplyAppPathModifier("~/Home/xrds")).AbsoluteUri);

  
06 return View("Index");

  
07 }

  
08

  
09 public ActionResult Xrds() {

  
10 return View("Xrds");

  
11 }

  
12 }

  XRDS 的View为:

  view sourceprint
?01

  
02

  
09

  
10 xmlns:xrds="xri://$xrds"

  
11 xmlns:openid="http://openid.net/xmlns/1.0"

  
12 xmlns="xri://$xrd*($v*2.0)">

  
13

  
14

  
15 http://specs.openid.net/auth/2.0/return_to

  这样就OK啰. 这只是简单的用法. 因为这个只返回很少信息. 一般只有两个,一个是:FriendlyIdentifierForDisplay ,就是用户名,一个是ClaimedIdentifier, 是用户的标识. 如果是这样用就OK,那我这文章也写得没什么意义了.呵. 因为一般我们还要抓到用户的Email,和个性图标.等等一些有用的东西.但是默认的是不返回的.

  先看看可以返回什么信息. DotNetOpenAuth中有一个WellKnownAttributes 类, 这个类中定义了一系列可以返回的信息. 下面是这个类的抓图:

  如何获取这些信息呢? 请看下面的示例代码 :

view sourceprint?01 [AcceptVerbs(HttpVerbs.Post)]

  
02 public ActionResult Login(string openid_identifier)

  
03 {

  
04 try

  
05 {

  
06 var openid = new OpenIdRelyingParty();

  
07 IAuthenticationRequest request = openid.CreateRequest(Identifier.Parse(openid_identifier));

  
08 var fetch = new FetchRequest();

  
09 fetch.Attributes.AddRequired(WellKnownAttributes.Contact.Email);

  
10 fetch.Attributes.AddRequired(WellKnownAttributes.Name.Alias);

  
11 fetch.Attributes.AddRequired(WellKnownAttributes.Name.FullName);

  
12 fetch.Attributes.AddRequired(WellKnownAttributes.Media.Images.Default);

  
13 request.AddExtension(fetch);

  
14

  
15 /*

  
16 request.AddExtension(new ClaimsRequest

  
17 {

  
18 Email = DemandLevel.Require,

  
19 FullName = DemandLevel.Require,

  
20 Nickname = DemandLevel.Require

  
21 });*/

  
22 return request.RedirectingResponse.AsActionResult();

  
23 }

  
24 catch

  
25 {

  
26 ViewData["ErrorMessage"] = "您输入的OpenID不正确或您的帐号的提供商不提供OpenID服务";

  
27

  
28 ViewData["OpenIDLoginURL"] = openid_identifier;

  
29 return View();

  
30 }

  
31 }

这样创建请求就可以成功获取你想要的信息了, 这里是请求获取 Email, 姓名, 个性图标.

  注意我注释了的代码, 一开始我也用这样,但是,这个无法获取个性图标.

  最后,最后很关键喔.. 配置文件!! 对.. 一开始我因为没注意这个,花了不少时间.. ======

  http://www.86e0.com 用的配置文件如下,基本是抄OpenIdRelyingPartyMvc 这个示例的.

  好了,现在基本没问题了.

  剩下就是在登录成功后获取这些信息了. 相关的代码如下:

view sourceprint?01 switch (response.Status) {

  
02 case AuthenticationStatus.Authenticated:

  
03 string nickName = response.FriendlyIdentifierForDisplay;

  
04 if (string.IsNullOrEmpty(nickName)) nickName = "匿名用户";

  
05 string email = string.Empty;

  
06 string picIcon = string.Empty;

  
07

  
08 if (nickName.Length > 50) { nickName = nickName.Substring(0, 50); }

  
09

  
10 var claim = response.GetExtension();

  
11 var fetch = response.GetExtension();

  
12

  
13 string picKey = WellKnownAttributes.Media.Images.Default;

  
14

  
15 if (fetch !=null && fetch.Attributes != null && fetch.Attributes.Contains(picKey))

  
16 {

  
17 var picAttr = fetch.Attributes[picKey];

  
18 if (picAttr != null && picAttr.Values.Count > 0) { picIcon = picAttr.Values[0]; }

  
19 }

  
20 if (claim != null)

  
21 {

  
22 nickName = claim.Nickname;

  
23

  
24 if (string.IsNullOrEmpty(nickName))

  
25 {

  
26 int ttIndex = claim.Email.IndexOf("@");

  
27 if (ttIndex > 0)

  
28 {

  
29 nickName = claim.Email.Substring(0, ttIndex);

  
30 }

  
31 else

  
32 {

  
33 nickName = claim.Email;

  
34 }

  
35 }

  
36 email = claim.Email;

  
37 }

  
38 // 最后授权,入库等.

  
39 case AuthenticationStatus.Canceled:

  
40 ViewData["Message"] = "Canceled at provider";

  
41 return View("Login");

  
42 case AuthenticationStatus.Failed:

  
43 ViewData["Message"] = response.Exception.Message;

  
44 return View("Login");

  
45 }

  OK了. 上面的这么多 if是因为抓出来的资料会有 null的情况.. 这个应该是用户没设定那些资料.

 

0
相关文章