Membership三步曲之入门篇 - Membership基础示例

Membership类成员介绍

  一般来讲我们的网站要实现的与用户相关的最基本功能包括:注册,登录,修改用户资料和密码。Membership为我们提供了以下几个类来帮助我们完成这些功能。

  在System.Web.Security的命名空间包含了上图中的8个类,但是实际上我们只需要Membership一个类就可以帮助我们完成大部份的功能。接下来我们就来一步一步的将Membership集成到我们的MVC站点中去。

集成Membership到ASP.NET MVC网站中

  这里我们的需求很简单,只是要实现一个包含注册、登录、以及修改密码功能的网站就可以了。我们接下来要做的就是建立一个基本的MVC站点,然后再配置Membership,加上我们的功能代码。

2.1 新建一个基本的MVC站点

  我们的站点默认已经启用Forms认证,如果不了解Foms的话,园子里面有一篇比较好的文章,我已经加上链接了。但是Forms有安全方面的隐患,这个系列的后面我们会对比各种认证方式,有兴趣的同学请继续关注。

  同时,还为我们默认配置了一个MembershipProvider(我们下面会说这个东西,这里暂时忽略也没有关系)

2.2 添加功能代码

  虽然说我们建立的这个项目已经配置好了Membership,但是并没有地方去使用它。我们没有Controller也没有View。所以接下来我们就要开始加入调用Membership的代码了。

  首先我们在Layout里面加上三个链接:Register, Login, 如果已经登录的话我们就显示用户名和LogOff。 

  当然我们还得加上HomeController并且添加一个默认的Index Action。然后我们再加上AccountController并且添加4个Action(Login和Register的Get、Post版本),View的代码我就不贴了,大家可以到未尾下载整个项目的源码。

登录代码

public ActionResult Login()
{
    return View();
}

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
    // Membership.ValidateUser 判断用户名和密码是否正确
    if (ModelState.IsValid && Membership.ValidateUser(model.UserName, model.Password))
    {
        // 调用Forms 的登录 User.Identity.IsAuthenticated 将设置为True
        // User.Identity.Name 会设置成我们下面的UserName
        FormsAuthentication.SetAuthCookie(model.UserName, false);
        return RedirectToLocal(returnUrl);
    }

    ModelState.AddModelError("", "The user name or password provided is incorrect.");
    return View(model);
}

注册相关代码

public ActionResult Register()
{
    return View();
}

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        try
        {   
            // Membership.CreateUser去创建用户
            var user = Membership.CreateUser(model.UserName, model.Password);
            if (user != null)
            {
                //注册完成之后直接登录用户
                FormsAuthentication.SetAuthCookie(user.UserName, false);
            }
            return RedirectToAction("Index", "Home");
        }
        catch (MembershipCreateUserException e)
        {
            ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
        }
    }
    return View(model);
}

登出相关代码

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    FormsAuthentication.SignOut();
    return RedirectToAction("Index", "Home");
}

修改密码相关代码

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    FormsAuthentication.SignOut();
    return RedirectToAction("Index", "Home");
}

[Authorize]
public ActionResult Manage()
{
    return View();
}

/**************************************************/
/*注意我们为Manage这两个Action加上了Authorize标签,只有登录过的用户才能访问
  如果用户没有登录直接访问/Account/Manage会被跳到/Account/Login要求登录*/

[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Manage(LocalPasswordModel model)
{
    if (ModelState.IsValid)
    {
        bool changePasswordSucceeded;
        try
        {
            var user = Membership.GetUser(User.Identity.Name);
            changePasswordSucceeded = user.ChangePassword(model.OldPassword,
                model.NewPassword);
        }
        catch (Exception)
        {
            changePasswordSucceeded = false;
        }

        if (changePasswordSucceeded)
        {
            return RedirectToAction("Manage", new { Message = "修改密码成功!"});
        }
        else
        {
            ModelState.AddModelError("", "老密码不正确或新密码不符合要求");
        }
    }
    return View(model);
}

  就是这么简单,我们的注册,登录,以及修改密码功能就完成了。

  来看一下我们用到了哪些Membership的功能:

  • Membership.ValidateUser 验证用户名和密码实现登录 
  • Membership.CreateUser 创建新用户
  • Membership.GetUser 获取用户
  • MembershipUser.ChangePassword 修改密码

  还有更多的方法我们可以使用,在最上面的表中我们已经列出来了,大家可以自行尝试。这些功能都出来以后,我们还有一个疑问没有解答,那就是我们的用户保存到哪里去了? 

  Membership的配置节点中有一个connctionStringName的属性,可以指定我们的数据库连接字符串。那我们就来看一下它都帮我们搞了一个什么样的数据库。注:这个数据库是Membership帮我们生成的,我之前并没有创建它,也就是我们只需要写好连接字符串就可以了。

  而我们的用户信息就保存在Users表和Memberships表中。

为Membership启用角色管理

  我们已经完成了登录、注册和修改密码的功能。登录属性认证的范畴,而与认证如影随形的还是授权。通俗的讲,认证是看这个用户是不是合法的,像一扇门,你放不放穿上用户进来。而授权是在他进来之后能够干什么,他可以坐在椅子上,但绝对不能坐在你头上,又或者你只允许你爸或者你老婆坐在你头上,这就是授权了。

  相信很多人都自己写过权限相关的代码,也有人会写出一套权限管理的框架来。其实ASP.NET已经有一套比较成熟的权限体系,加上它的自定义功能基本可以满足我们大多数的需求了。

  在我们创建这个MVC站点的时候,VS也为我们配置了权限模块。就在挨着membership结点的下方:

  因为我们这里面的连接字符串与我们的membersihp中用到的是同一个,所以和权限相关的表Roles、UserInRoles也创建到了同一个数据库中。不一样的是我们不需要写一行代码就可以完成角色管理的功能,包括创建/修改/删除角色,以及给用户赋予角色。

  通过项目->ASP.NET 配置就可以打开这个小网站去管理我们的角色(抱歉,我用的英文版 - -! )。

  我们可以点击Security(安全)到管理用户和角色的地页面。

我们先添加3个角色:Admin, Manager, User

然后我们就可以给我们的用户赋予角色了。

  接下来我们就可以在代码中使用User.IsInRole方法是看用户是否具有某一个角色的权限了。在MVC的Action上我们可以直接在Authorize标签中指定某个角色,那么这个Action就只有这个角色下的用户才能够访问了。

[Authorize(Roles="Admin")]
public ActionResult Manage()
{
    return View();
}

  我们还可以通过调用Roles.GetRolesForUser将这个用户相关的角色的都取出来。

  现在我们就已经为我们的网站添加认证和授权模块了,分分搞定啊!功能是完成了,但是还留下了不少的问题需要解决,因为大多数情况下我们的User表都不会这么简单,要多加一些字段怎么办? 我们使用了EF需要使用User entity怎么办?又或者角色是有父子关系的又该如何做呢?我们后面的进阶篇将会告诉你答案。

  Demo下载:http://pan.baidu.com/s/1gduY5CR (你点或不点,推荐按钮就在右下角 !)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Urahara Blog

Windows上传并执行恶意代码的N种姿势

1302
来自专栏乐沙弥的世界

RMAN 概述及其体系结构

是一种用于集备份(backup)、还原(restore)和恢复(recover)数据库于一体的Oracle 工具,支持命令行及图形界面操作

701
来自专栏崔庆才的专栏

分布式爬虫原理之Scrapy分布式实现

1796
来自专栏ascii0x03的安全笔记

PySide——Python图形化界面入门教程(五)

PySide——Python图形化界面入门教程(五)               ——QListWidget 翻译自:http://pythoncentral....

2766
来自专栏磨磨谈

rados put striper功能的调试

之前对于striper这个地方的功能并没研究太多,只是知道这个里面可以以条带方式并行的去写对象,从而加大并发性来提高性能,而默认的条带数目为1,也就是以对象大小...

673
来自专栏乐沙弥的世界

Linux网络检测相关工具用法(ping/netstat/ss/ethtool)

当新的Linux主机完成了网络配置,即可以正常接入网络后,我们可以通过Linux自带的相关工具进行网络相关检测。如最常用的ping,netstat,ss,tra...

743
来自专栏哎_小羊

初试 Netflix 开源持续云交付平台 Spinnaker

目录 Spinnaker 介绍 环境、软件准备 安装 Development Spinnaker 配置依赖环境 配置并安装 Spinnaker 演示 Spi...

9848
来自专栏逸鹏说道

Linux 部署ASP.NET SQLite 应用 的坎坷之旅 附demo及源码

Linux 部署ASP.NET SQLite 应用 的坎坷之旅。文章底部 附示例代码。 有一台闲置的Linux VPS,尝试着部署一下.NET 程序,结果就踏上...

2623
来自专栏IT笔记

JavaWeb项目架构之FastDFS分布式文件系统

分布式文件系统:Distributed file system, DFS,又叫做网络文件系统:Network File System。一种允许文件通过网络在多台...

4215
来自专栏大内老A

从数据到代码——通过代码生成机制实现强类型编程[下篇]

在《上篇》中,我们实现了将保存有消息条目的XML向CodeDOM的转换,即是将XML文件生成一个CodeCompileUnit对象,而该CodeCompileU...

1806

扫描关注云+社区