Asp.net mvc 使用自定义身份提供程序Dotnetopenauth单点登录

Asp.net mvc 使用自定义身份提供程序Dotnetopenauth单点登录,asp.net-mvc,asp.net-mvc-4,dotnetopenauth,Asp.net Mvc,Asp.net Mvc 4,Dotnetopenauth,我正在尝试将DotNetOpenAuth示例设置为具有自定义提供程序的可用SSO解决方案。我正在使用OpenIdProviderMvc示例项目,该项目似乎运行良好 我的问题是设置“消费者”,在本例中是OpenIdRelyingPartyMvc示例项目,我无法将其配置为使用OpenIdProvider 我尝试在消费者的web.config上设置端点,如下所示: <trustedProviders rejectAssertionsFromUntrustedProviders="true">

我正在尝试将DotNetOpenAuth示例设置为具有自定义提供程序的可用SSO解决方案。我正在使用OpenIdProviderMvc示例项目,该项目似乎运行良好

我的问题是设置“消费者”,在本例中是OpenIdRelyingPartyMvc示例项目,我无法将其配置为使用OpenIdProvider

我尝试在消费者的web.config上设置端点,如下所示:

<trustedProviders rejectAssertionsFromUntrustedProviders="true">
    <add endpoint="http://localhost:4864/OpenID/Provider" />
</trustedProviders>
public class LogOnModel
{
    [Display(Name = "OpenID")]
    public string OpenID { get; set; }

    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}
public interface IMembershipService
{
    int MinPasswordLength { get; }
    bool ValidateUser(string userName, string password);
    MembershipCreateStatus CreateUser(string userName, string password,
                                      string email, string OpenID);
    bool ChangePassword(string userName, string oldPassword, string newPassword);
    MembershipUser GetUser(string OpenID);
}
public MembershipCreateStatus CreateUser(string userName, string password, 
                                         string email , string OpenID)
{
    if (String.IsNullOrEmpty(userName)) throw 
    new ArgumentException("Value cannot be null or empty.", "userName");
    if (String.IsNullOrEmpty(password)) throw 
    new ArgumentException("Value cannot be null or empty.", "password");
    if (String.IsNullOrEmpty(email)) throw
    new ArgumentException("Value cannot be null or empty.", "email");

    MembershipCreateStatus status;
    _provider.CreateUser(userName, password, email, null, null, true,
                            StringToGUID(OpenID), out status);
    return status;
}

但我得到的只是“找不到OpenID端点”。错误(实际上,我不太确定在OpenID框中放置什么…)

这个项目实际上没有记录在案。有人能给我指出正确的方向吗

至少让供应商和消费者彼此工作和交谈?

让我们开始:

1-打开Visual Studio 2010转到文件>新建>项目>Web>ASP.NET MVC 3应用程序:

然后选择Internet应用程序确保使用Razor作为查看引擎,然后单击“确定”:

2-,它包含我们将使用的dll和OpenID选择器文件

如果您想进入这些项目并了解更多细节,请随意

将其解压缩到所需的文件夹中

  a - Add the DotNetOpenAuth.dll to references in your site.

  b- Delete all files/folders in Site Content folder.

  c- Copy Assets Content files/folders to the site Content .

  d- Copy the  Assets Script files to the site Script.

您的项目将如下所示:

3-转到视图>共享>\u Layout.cshtml并用此新标题替换,我们刚刚添加了新样式和脚本:

<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" 
     rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")"
     type="text/javascript"></script>
    <link href="@Url.Content("~/Content/openid-shadow.css")"
     rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/openid.css")" 
     rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/openid-en.js")" 
     type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/openid-jquery.js")" 
     type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            openid.init('openid_identifier');
        });
    </script>
</head>
导航到公共类RegisterModel并添加OpenID属性

public class RegisterModel
{

    [Display(Name = "OpenID")]
    public string OpenID { get; set; }

    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email address")]
    public string Email { get; set; }

    [Required]
    [ValidatePasswordLength]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage =
    "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}
然后转到AccountModels.cs中的服务部分

using System.Security.Cryptography;
using System.Text;
并修改CreateUser并添加GetUser,以通过接口OpenID获取用户

威尔看起来像这样:

<trustedProviders rejectAssertionsFromUntrustedProviders="true">
    <add endpoint="http://localhost:4864/OpenID/Provider" />
</trustedProviders>
public class LogOnModel
{
    [Display(Name = "OpenID")]
    public string OpenID { get; set; }

    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}
public interface IMembershipService
{
    int MinPasswordLength { get; }
    bool ValidateUser(string userName, string password);
    MembershipCreateStatus CreateUser(string userName, string password,
                                      string email, string OpenID);
    bool ChangePassword(string userName, string oldPassword, string newPassword);
    MembershipUser GetUser(string OpenID);
}
public MembershipCreateStatus CreateUser(string userName, string password, 
                                         string email , string OpenID)
{
    if (String.IsNullOrEmpty(userName)) throw 
    new ArgumentException("Value cannot be null or empty.", "userName");
    if (String.IsNullOrEmpty(password)) throw 
    new ArgumentException("Value cannot be null or empty.", "password");
    if (String.IsNullOrEmpty(email)) throw
    new ArgumentException("Value cannot be null or empty.", "email");

    MembershipCreateStatus status;
    _provider.CreateUser(userName, password, email, null, null, true,
                            StringToGUID(OpenID), out status);
    return status;
}
使用AccountModels.cs添加这些

using System.Security.Cryptography;
using System.Text;
然后将此函数添加到AccountModels.cs,此函数将用于将OpenID转换为GUID

注意:可以对您的系统使用更好的哈希,MD5有一些冲突问题

public Guid StringToGUID(string value)
{
    // Create a new instance of the MD5CryptoServiceProvider object.
    MD5 md5Hasher = MD5.Create();
    // Convert the input string to a byte array and compute the hash.
    byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(value));
    return new Guid(data);
}
还要修改CreateUser函数,使其如下所示:

<trustedProviders rejectAssertionsFromUntrustedProviders="true">
    <add endpoint="http://localhost:4864/OpenID/Provider" />
</trustedProviders>
public class LogOnModel
{
    [Display(Name = "OpenID")]
    public string OpenID { get; set; }

    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}
public interface IMembershipService
{
    int MinPasswordLength { get; }
    bool ValidateUser(string userName, string password);
    MembershipCreateStatus CreateUser(string userName, string password,
                                      string email, string OpenID);
    bool ChangePassword(string userName, string oldPassword, string newPassword);
    MembershipUser GetUser(string OpenID);
}
public MembershipCreateStatus CreateUser(string userName, string password, 
                                         string email , string OpenID)
{
    if (String.IsNullOrEmpty(userName)) throw 
    new ArgumentException("Value cannot be null or empty.", "userName");
    if (String.IsNullOrEmpty(password)) throw 
    new ArgumentException("Value cannot be null or empty.", "password");
    if (String.IsNullOrEmpty(email)) throw
    new ArgumentException("Value cannot be null or empty.", "email");

    MembershipCreateStatus status;
    _provider.CreateUser(userName, password, email, null, null, true,
                            StringToGUID(OpenID), out status);
    return status;
}
这里我们使用MemberShip ProviderUserKey存储OpenID,这里的技巧是将OpenID字符串转换为GUID,以供CreateUser和GetUser方法使用

现在,让我们将此函数添加到AccountModels.cs,该函数将通过OpenID获取用户:

public MembershipUser GetUser(string OpenID)
{
    return _provider.GetUser(StringToGUID(OpenID), true);
}
5-转到视图>帐户>登录.cshtml

将所有标记替换为此标记,我们正在将OpenID选择器集成到登录视图:

@model OpenIDMVC3.Models.LogOnModel
@{
    ViewBag.Title = "Log On";
}
<h2>
    Log On</h2>
<p>
    Please enter your username and password. @Html.ActionLink("Register", "Register")
    if you don't have an account.
</p>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript">
</script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
   type="text/javascript"></script>
<form action=
"Authenticate?ReturnUrl=@HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"])"
 method="post" id="openid_form">
<input type="hidden" name="action" value="verify" />
<div>
    <fieldset>
        <legend>Login using OpenID</legend>
        <div class="openid_choice">
            <p>
                Please click your account provider:</p>
            <div id="openid_btns">
            </div>
        </div>
        <div id="openid_input_area">
            @Html.TextBox("openid_identifier")
            <input type="submit" value="Log On" />
        </div>
        <noscript>
            <p>
                OpenID is service that allows you to log-on to many different websites 
                using a single indentity. Find out <a href="http://openid.net/what/">
                 more about OpenID</a>and <a href="http://openid.net/get/">
                 how to get an OpenID enabled account</a>.</p>
        </noscript>
        <div>
            @if (Model != null)
            {
                if (String.IsNullOrEmpty(Model.UserName))
                {
                <div class="editor-label">
                    @Html.LabelFor(model => model.OpenID)
                </div>
                <div class="editor-field">
                    @Html.DisplayFor(model => model.OpenID)
                </div>
                <p class="button">
                    @Html.ActionLink("New User ,Register", "Register", 
                                         new { OpenID = Model.OpenID })
                </p>
                }
                else
                {
                    //user exist 
                <p class="buttonGreen">
                    <a href="@Url.Action("Index", "Home")">Welcome , @Model.UserName, 
                    Continue..." </a>
                </p>

                }
            }
        </div>
    </fieldset>
</div>
</form>

@Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors 
                                                    and try again.")
@using (Html.BeginForm())
{
    <div>
        <fieldset>
            <legend>Or Login Normally</legend>
            <div class="editor-label">
                @Html.LabelFor(m => m.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.UserName)
                @Html.ValidationMessageFor(m => m.UserName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(m => m.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.Password)
                @Html.ValidationMessageFor(m => m.Password)
            </div>
            <div class="editor-label">
                @Html.CheckBoxFor(m => m.RememberMe)
                @Html.LabelFor(m => m.RememberMe)
            </div>
            <p>
                <input type="submit" value="Log On" />
            </p>
        </fieldset>
    </div>
}
然后将此属性添加到AccountController.cs:

private static OpenIdRelyingParty openid = new OpenIdRelyingParty();
[ValidateInput(false)]
public ActionResult Authenticate(string returnUrl)
{
    var response = openid.GetResponse();
    if (response == null)
    {
        //Let us submit the request to OpenID provider
        Identifier id;
        if (Identifier.TryParse(Request.Form["openid_identifier"], out id))
        {
            try
            {
                var request = openid.CreateRequest(
                                        Request.Form["openid_identifier"]);
                return request.RedirectingResponse.AsActionResult();
            }
            catch (ProtocolException ex)
            {
                ViewBag.Message = ex.Message;
                return View("LogOn");
            }
        }

        ViewBag.Message = "Invalid identifier";
        return View("LogOn");
    }

    //Let us check the response
    switch (response.Status)
    {

        case AuthenticationStatus.Authenticated:
            LogOnModel lm = new LogOnModel();
            lm.OpenID = response.ClaimedIdentifier;
            // check if user exist
            MembershipUser user = MembershipService.GetUser(lm.OpenID);
            if (user != null)
            {
                lm.UserName = user.UserName;
                FormsService.SignIn(user.UserName, false);
            }

            return View("LogOn", lm);

        case AuthenticationStatus.Canceled:
            ViewBag.Message = "Canceled at provider";
            return View("LogOn");
        case AuthenticationStatus.Failed:
            ViewBag.Message = response.Exception.Message;
            return View("LogOn");
    }

    return new EmptyResult();
}
然后将此函数添加到AccountController.cs:

private static OpenIdRelyingParty openid = new OpenIdRelyingParty();
[ValidateInput(false)]
public ActionResult Authenticate(string returnUrl)
{
    var response = openid.GetResponse();
    if (response == null)
    {
        //Let us submit the request to OpenID provider
        Identifier id;
        if (Identifier.TryParse(Request.Form["openid_identifier"], out id))
        {
            try
            {
                var request = openid.CreateRequest(
                                        Request.Form["openid_identifier"]);
                return request.RedirectingResponse.AsActionResult();
            }
            catch (ProtocolException ex)
            {
                ViewBag.Message = ex.Message;
                return View("LogOn");
            }
        }

        ViewBag.Message = "Invalid identifier";
        return View("LogOn");
    }

    //Let us check the response
    switch (response.Status)
    {

        case AuthenticationStatus.Authenticated:
            LogOnModel lm = new LogOnModel();
            lm.OpenID = response.ClaimedIdentifier;
            // check if user exist
            MembershipUser user = MembershipService.GetUser(lm.OpenID);
            if (user != null)
            {
                lm.UserName = user.UserName;
                FormsService.SignIn(user.UserName, false);
            }

            return View("LogOn", lm);

        case AuthenticationStatus.Canceled:
            ViewBag.Message = "Canceled at provider";
            return View("LogOn");
        case AuthenticationStatus.Failed:
            ViewBag.Message = response.Exception.Message;
            return View("LogOn");
    }

    return new EmptyResult();
}
8-现在运行该项目,点击[登录]链接,然后点击谷歌等提供商

它可能会要求您登录或要求您允许访问您的信息

您将获得如下页面:

如您所见,它显示您的OpenID和一个按钮,指示这是一个尚未注册的新用户

在点击[New User,Register]按钮之前,我们需要修改Register视图和控制器以访问OpenID信息

9-转到控制器>AccountController.cs,将[ActionResult寄存器()]替换为:

public ActionResult Register(string OpenID)
{
    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
    ViewBag.OpenID = OpenID;
    return View();
}
@model OpenIDMVC3.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

<h2>Create a New Account</h2>
<p>
    Use the form below to create a new account. 
</p>
<p>
    Passwords are required to be a minimum of @ViewBag.PasswordLength 
    characters in length.
</p>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 
  type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
   type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true, "Account creation was unsuccessful.
                                            Please correct the errors and try again.")
    <div>
        <fieldset>
            <legend>Account Information</legend>
            @if (ViewData["OpenID"] != null)
            {
            <div class="editor-label">
                @Html.Label("OpenID")
            </div>
            <div class="editor-label">
                @Html.Label((string)ViewBag.OpenID)
            </div>
            }
            <div class="editor-label">
                @Html.LabelFor(m => m.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.UserName)
                @Html.ValidationMessageFor(m => m.UserName)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Email)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.Email)
                @Html.ValidationMessageFor(m => m.Email)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.Password)
                @Html.ValidationMessageFor(m => m.Password)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.ConfirmPassword)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.ConfirmPassword)
                @Html.ValidationMessageFor(m => m.ConfirmPassword)
            </div>

            <p>
                <input type="submit" value="Register" />
            </p>
        </fieldset>
    </div>
}
并修改[ActionResult寄存器(RegisterModel模型)]以在

创建用户:

[HttpPost]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        // Attempt to register the user
        MembershipCreateStatus createStatus =
        MembershipService.CreateUser(model.UserName, model.Password, 
                                        model.Email,model.OpenID);

        if (createStatus == MembershipCreateStatus.Success)
        {
            FormsService.SignIn(model.UserName, false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            ModelState.AddModelError("",
            AccountValidation.ErrorCodeToString(createStatus));
        }
    }

    // If we got this far, something failed, redisplay form
    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
    return View(model);
}
10-转到视图>帐户>Register.cshtml,将标记替换为以下内容:

public ActionResult Register(string OpenID)
{
    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
    ViewBag.OpenID = OpenID;
    return View();
}
@model OpenIDMVC3.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

<h2>Create a New Account</h2>
<p>
    Use the form below to create a new account. 
</p>
<p>
    Passwords are required to be a minimum of @ViewBag.PasswordLength 
    characters in length.
</p>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 
  type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
   type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true, "Account creation was unsuccessful.
                                            Please correct the errors and try again.")
    <div>
        <fieldset>
            <legend>Account Information</legend>
            @if (ViewData["OpenID"] != null)
            {
            <div class="editor-label">
                @Html.Label("OpenID")
            </div>
            <div class="editor-label">
                @Html.Label((string)ViewBag.OpenID)
            </div>
            }
            <div class="editor-label">
                @Html.LabelFor(m => m.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.UserName)
                @Html.ValidationMessageFor(m => m.UserName)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Email)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.Email)
                @Html.ValidationMessageFor(m => m.Email)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.Password)
                @Html.ValidationMessageFor(m => m.Password)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.ConfirmPassword)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.ConfirmPassword)
                @Html.ValidationMessageFor(m => m.ConfirmPassword)
            </div>

            <p>
                <input type="submit" value="Register" />
            </p>
        </fieldset>
    </div>
}
@model OpenIDMVC3.Models.RegisterModel
@{
ViewBag.Title=“寄存器”;
}
创建新帐户

使用下表创建新帐户。

密码必须至少为@ViewBag.PasswordLength 字符长度。

@使用(Html.BeginForm()){ @Html.ValidationSummary(true),“帐户创建失败。 请更正错误,然后重试。“) 帐户信息 @如果(ViewData[“OpenID”]!=null) { @Html.Label(“OpenID”) @Label((字符串)ViewBag.OpenID) } @LabelFor(m=>m.UserName) @Html.TextBoxFor(m=>m.UserName) @Html.ValidationMessageFor(m=>m.UserName) @LabelFor(m=>m.Email) @Html.TextBoxFor(m=>m.Email) @Html.ValidationMessageFor(m=>m.Email) @LabelFor(m=>m.Password) @Html.PasswordFor(m=>m.Password) @Html.ValidationMessageFor(m=>m.Password) @LabelFor(m=>m.ConfirmPassword) @Html.PasswordFor(m=>m.ConfirmPassword) @Html.ValidationMessageFor(m=>m.ConfirmPassword)

}
11-转到步骤8,让我们点击[新用户,注册]按钮,您将得到以下结果:

12-注册您想要的任何帐户,您将获得如下页面:

13-单击[注销]并使用相同的OpenID再次登录,您将获得如下页面:

如您所见,欢迎绿色按钮检测该用户已注册

14-单击绿色按钮,您将看到如下页面:

祝贺你,现在,您已经将OpenID集成到了项目中


非常完整的教程。。。参考链接似乎没有指向您可能认为它的功能。谢谢,但是,如何将其链接到自定义提供商?ie,我自己的身份验证提供商?值得一提的是:我在运行示例()时没有遇到任何问题。我没有取消对trusted providers部分的注释,而是在VS中为服务器和客户机启动了两个实例,并只是在OpenId框中输入。默认情况下,我猜示例客户机将接受任何openId提供程序。