在mvc app中进行身份验证,使用外部服务进行身份验证

时间:2012-10-21 18:23:29

标签: c# asp.net-mvc security asp.net-mvc-4 forms-authentication

我目前正在开发一个MVC4应用程序,其中不同类型的用户可以访问该站点并登录。将有2种不同的用户分类,类型A和B,可以访问该站点的不同区域。

用户的身份验证是通过对身份验证提供程序的服务调用,他们将返回用户是否已经过身份验证的状态以及用户信息,例如姓名,地址等。此时我想跟踪用户已经过身份验证以及他们所处的角色。以前我会创建一个包含用户名,地址等并存储在客户端计算机上的cookie。但由于cookie是纯文本,因此可以操作。

但我想加强网站的安全性,因此我们希望使用FormsAuthentication。我知道生成一个cookie但它更安全。

这是正确的方法吗?地址等用户信息是否可以存储在此cookie中?我想要存储它的会话。我如何使用FormsAuthentication实现这一目标?

我的第二个问题是,一旦用户登录,我如何知道他们所处的角色?

最后,一旦用户登录,整个网站应该通过https吗?即使是对所有人开放但被登录用户访问的区域?登录用户将在每个页面上显示屏幕上显示的信息,例如欢迎约翰。

1 个答案:

答案 0 :(得分:4)

  

这是正确的方法吗?地址等用户信息是否可以存储在此cookie中?

您是正确的,表单身份验证默认情况下会将用户详细信息存储在加密的Cookie中,因此它比您现在拥有的更安全。

使用表单身份验证,您可以指定进入客户端cookie的字符串内容。但是,我认为您应该在cookie中存储的唯一信息是用户标识符和角色标识符。此信息应该是每个请求对用户进行身份验证和授权所必需的全部信息。任何额外的信息(如地址)都会增加cookie的权重,并且可以在需要时从服务中获取。

要使用表单身份验证,只需将Authentication元素添加到system.web部分中的web.config:

<authentication mode="Forms">
  <forms loginUrl="~/Login/Home" timeout="60" />
</authentication>

调用服务以验证用户后,通过FormsAuthentication静态类设置Cookie数据。 Cookie数据需要包含用户的标识符(例如,如果要显示用户的名称)和角色标识符(如下所述)。

var username = // get name from service
var role = // get role from service
FormsAuthentication.SetAuthCookie(username + "-" + role, keepUserLoggedIn);

当用户退出时,使用相同的类删除cookie。

FormsAuthentication.SignOut();

  

我的第二个问题是,一旦用户登录,我如何知道他们所处的角色?

asp.net MVC提供了一种简单的机制,允许您的应用程序区域仅限于特定用户。通过在任何控制器类或操作方法上使用[Authorise]属性,只允许登录用户访问 - 即存在FormsAuthentication cookie的用户。未登录的用户将被重定向到web.config的authenication元素中指定的LoginUrl。

Authorize属性也有一个重载,只允许特定角色的用户访问控制器/方法。这将仅允许处于“Admin”角色的登录用户访问控制器的任何操作方法。

[Authroise("Admin")]
public class EditController : Controller
{}

然后,您需要创建自己的系统接口RoleProvider实现。界面包含许多方法,但并非所有方法都是必需的。您需要实现的唯一方法是检查用户所在的角色是GetRolesForUser[Authorise]属性将使用此选项来确定用户是否可以查看。

public class MyRoleProvider : RoleProvider
{
    public override string[] GetRolesForUser(string username)
    {
        var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];

        if (authCookie != null && !String.IsNullOrEmpty(authCookie.Value))
        {
            var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            var roles = authTicket.UserData.Split(',')[1];
            return roles.Split(';');
        }

        throw new MemberAccessException("User not logged in");
    }
}

然后,当RoleProvider属性启动时,您只需要告诉您的应用程序使用Authorise]的实现。这也是通过system.web元素中的web.config完成的。

<roleManager defaultProvider="MyRoleProvider" enabled="true">
  <providers>
    <clear />
    <add name="MyRoleProvider" type="My.Namespace.MyRoleProvider" />
  </providers>
</roleManager>

  

最后,一旦用户登录,整个网站应该通过https吗?即使是对所有人开放但被登录用户访问的区域?

理想情况下,是的。一旦用户登录并且您已设置FormsAuthentication cookie,您需要保护该cookie免受外部拦截。为防止这种情况,您应该在应用程序的所有区域强制执行https协议。如果拦截了用户的请求并制作了cookie的副本,则“中间人”可以在其浏览器中设置cookie的副本并访问您站点的受保护区域。使用MVC,您可以在任何特定控制器或操作方法上使用[RequireHttpsAttribute],类似于[Authorise]属性。在MVC4中,有一种简单的方法可以应用这种“全球”。在您的Web项目的App_Start文件夹中,找到FilterConfig类,并在RegisterGlobalFilters方法中包含以下行:

filters.Add(new RequireHttpsAttribute());