针对外部Web服务的ASP.NET MVC Forms身份验证

Tom*_*igh 24 c# asp.net asp.net-mvc web-services forms-authentication

我正在尝试编写一个ASP.NET MVC应用程序,它是我们的CRM的前端,它具有SOAP Web服务.我希望用户使用他们的CRM用户名和密码登录我的Web应用程序,然后针对CRM进行身份验证,在页面上进行Web服务调用等.

我开始考虑使用表单身份验证和实现自定义成员资格提供程序 - 我可以实现我需要的所有方法ValidateUser(),但我遇到的问题是登录到CRM Web服务后,您将获得一个必须的令牌每次后续的Web服务调用都会通过,我不知道我可以在哪里存储它.

所以我的问题是:

  • 是表单身份验证的方式,或者是自己处理所有身份验证并将令牌存储在Session中更直接.
  • 如果要进行表单身份验证,我应该在何处以及如何存储此类附加信息.似乎喜欢使用表单身份验证,但随后将一大堆附加信息(与身份验证相关)压入cookie或会话以外的会话会有点混乱?

任何意见,将不胜感激

Dar*_*rov 36

您可以将身份验证令牌存储在窗体身份验证cookie的userData部分中.这样,每次请求都可以使用它.

因此,例如,一旦验证了用户的凭据,您就可以查询Web服务以获取令牌并手动创建并发出表单身份验证cookie:

[HttpPost]
public ActionResult LogOn(string username, string password)
{
    // TODO: verify username/password, obtain token, ...
    // and if everything is OK generate the authentication cookie like this:

    var authTicket = new FormsAuthenticationTicket(
        2,
        username,
        DateTime.Now,
        DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
        false,
        "some token that will be used to access the web service and that you have fetched"
    );
    var authCookie = new HttpCookie(
        FormsAuthentication.FormsCookieName, 
        FormsAuthentication.Encrypt(authTicket)
    )
    {
        HttpOnly = true
    };
    Response.AppendCookie(authCookie);

    // ... redirect
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以编写自定义authorize属性,该属性将读取此信息并设置自定义通用标识:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthenticated = base.AuthorizeCore(httpContext);
        if (isAuthenticated) 
        {
            string cookieName = FormsAuthentication.FormsCookieName;
            if (!httpContext.User.Identity.IsAuthenticated ||
                httpContext.Request.Cookies == null || 
                httpContext.Request.Cookies[cookieName] == null)
            {
                return false;
            }

            var authCookie = httpContext.Request.Cookies[cookieName];
            var authTicket = FormsAuthentication.Decrypt(authCookie.Value);

            // This is where you can read the userData part of the authentication
            // cookie and fetch the token
            string webServiceToken = authTicket.UserData;

            IPrincipal userPrincipal = ... create some custom implementation
                                           and store the web service token as property

            // Inject the custom principal in the HttpContext
            httpContext.User = userPrincipal;
        }
        return isAuthenticated;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后装饰需要使用此属性进行身份验证的控制器/操作:

[MyAuthorize]
public ActionResult Foo()
{
    // HttpContext.User will represent the custom principal you created
    // and it will contain the web service token that you could use to 
    // query the remote service
    ...
}
Run Code Online (Sandbox Code Playgroud)