WebAPI + SimpleMembership + WebSecurity - 永远无法进行身份验证?

Posted

技术标签:

【中文标题】WebAPI + SimpleMembership + WebSecurity - 永远无法进行身份验证?【英文标题】:WebAPI + SimpleMembership + WebSecurity - can never authenticate? 【发布时间】:2014-11-29 15:32:52 【问题描述】:

我正在尝试实现一个单页应用程序。我从另一个项目(MVC4)中继承了我的一些工作代码来实现身份验证。现在我看到 cookie 正在设置,但 WebSecurity / User.Identity 似乎由于某种原因无法正常工作。登录后,后续请求从不通过WebSecurity.IsAuthenticatedUser.Identity.IsAuthenticated 验证为已通过身份验证。有谁知道为什么会这样?

控制器代码:

public class AccountController : ApiController 

    private readonly UserService _userService;

    public AccountController() 

    public AccountController(UserService userService) 
        _userService = userService;
    

    [AllowAnonymous]
    [HttpGet]
    [Route("api/authpayload")]
    // This gets called when the app loads.  Always, User.Identity.IsAuthenticated is false. 
    public HttpResponseMessage AuthPayload() 
        var payload = new AuthPayloadDto();
        try 
            var userId = WebSecurity.GetUserId(User.Identity.Name);
            if (User.Identity.IsAuthenticated && userId > 0) 
                payload.Username = User.Identity.Name;
             else 
                LogOut();
                payload.IsAuthenticated = false;
            
            return Request.CreateResponse(HttpStatusCode.OK, payload);
         catch (Exception e) 
            return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
        
    

    [HttpPost]
    [Route("api/login")]
    [AllowAnonymous]
    public HttpResponseMessage LogIn(LoginModel model) 
        if (!ModelState.IsValid)
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        try 
            if (WebSecurity.IsAuthenticated)
                return Request.CreateResponse(HttpStatusCode.Conflict, "already logged in.");
            if (!WebSecurity.UserExists(model.Username))
                return Request.CreateResponse(HttpStatusCode.Conflict, "User does not exist.");
            if (WebSecurity.Login(model.Username, model.Password, persistCookie: model.RememberMe)) 
                // This code always gets hit when I log in, no problems.  I see a new cookie get sent down as well, using Chrome debugger.
                var payload = new AuthPayloadDto();
                return Request.CreateResponse(HttpStatusCode.OK, payload);
            
            LogOut();
            return Request.CreateResponse(HttpStatusCode.Forbidden, "Login Failed.");
         catch (Exception e) 
            return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
        
    

Web.config:

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <authentication mode="Forms">
      <forms loginUrl="~/" timeout="2880" />
    </authentication>
    <roleManager enabled="true" defaultProvider="simple">
      <providers>
        <clear />
        <add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
      </providers>
    </roleManager>
    <membership defaultProvider="simple">
      <providers>
        <clear />
        <add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>
    <!--
            If you are deploying to a cloud environment that has multiple web server instances,
            you should change session state mode from "InProc" to "Custom". In addition,
            change the connection string named "DefaultConnection" to connect to an instance
            of SQL Server (including SQL Azure and SQL  Compact) instead of to SQL Server Express.
      -->
    <sessionState mode="InProc" customProvider="DefaultSessionProvider">
      <providers>
        <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
      </providers>
    </sessionState>

  </system.web>

登录后发送的 cookie 没有过期,并且会在后续请求中返回,但 IsAuthenticated 始终为 false。我做错了什么?

更新:

我将 web.config 更新为以下内容以使一切正常:

<system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
      <providers>
        <clear />
        <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
      </providers>
    </roleManager>
    <membership defaultProvider="SimpleMembershipProvider">
      <providers>
        <clear />
        <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>
  </system.web>

但我想保持开放状态,以防有人解释为什么会这样;我很迷茫。

【问题讨论】:

根据我的个人经验,我永远无法通过 MVC 的 Web API(使用 MVC 4 和 5)获得身份验证。如果用户通过 MVC 的社交登录登录,那么我可以检查当前用户是否通过 Web API 登录。但是尝试实际登录用户一直是一个挑战。还有其他第三方身份验证服务可与 MVC 一起解决此问题(如 auth0.com)。 您的问题解决了吗?我也面临同样的问题..它成功验证了用户,但经过身份验证仍然是错误的。 【参考方案1】:

在我当前使用 mssql 的 mvc 4 项目中, 这是一个简单的我,所以我只想要非常简单的会员资格提供者 我禁用了 初始化SimpleMembershipAttribute

[Authorize]
//[InitializeSimpleMembership]
public partial class AccountController : Controller

并将此代码添加到 Application_Start 下的 global.asax

WebSecurity.InitializeDatabaseConnection(
             connectionStringName: "DefaultConnection",
             userTableName: "UserProfile",
             userIdColumn: "UserID",
             userNameColumn: "UserName",
             autoCreateTables: true);

在我的 sql 数据库中,应用程序在其中创建了一些表是 Roles,而 UserInRoles 只是添加了我需要的角色,例如管理员、客户等... 我通过添加此代码来限制对某些控制器或操作的访问

[Authorize(Roles = "Admin")]
public class MessagesController : Controller

【讨论】:

以上是关于WebAPI + SimpleMembership + WebSecurity - 永远无法进行身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

实体框架代码优先问题(SimpleMembership UserProfile 表)

MVC 密码重置邮件 NO SIMPLEMEMBERSHIP

使用 simplemembership 的新 MVC 4 Internet 模板中基于角色的身份验证

Simplemembership ASPXAUTH cookie 在两个单独的 Web 项目上进行验证

如何将我自己的数据库与 SimpleMembership 和 WebSecurity 一起使用?啥是 MVC4 安全性?

SimpleMembership 会在 MVC3 DB 优先应用程序中工作吗?