笔记:ASP.NET MVC 个人用户认证

起因:要上线一个内部的小系统,于是就动手实现,不过以前属于纯玩票,现在毕竟要实际用的东西,认证就要做了,后期要把认证绑到公司域的AD上,但是现在没有权限的情况下,内部测试只能用本地的认证系统了。

开始在完全搞不懂MVC这部分的情况下,想得蛮简单,小范围测试只需要几个人,手动创建完帐号字典,连数据库都不用,直接明文一验证就完了。结果发现框架里已经提供了比较完事的认证系统,就直接用吧,但是不会用……

经过一些时间的搜索,先记录一下。

首先依赖数据库,会使用LocalDB在App_data目录下生成一个mdf的LocalDB文件,一共5张表,用户的,用户组的,映射关系什么的,开始可以先不管。

在创建完框架直接调试,可以进入注册页面,先注册一个帐号,会要求用邮箱,密码也有复杂性要求,这部分如果要修改可以在App_Start\IdentityConfig.cs文件里修改PasswordValidator。

创建完,会发现本地数据库的表AspNetUsers里会多一个用户。当然密码不会用明文存……

然后我的需求1是帐号密码可以由我一个人创建,2是其他人可以登陆,但是不能创建新帐户。

尝试1:直接修改数据库,添加条目,发现AspNetUsers表里的ID是hash值,手动创建其实修改成数字应该也可以,不过显得不专业,放弃。

尝试2:注册、注销,循环注册多个帐户,太傻,放弃。

尝试3:登陆完注册导航按钮消失,直接输入url可以不?可以……这个办法已经可以了,偷懒的话可以把注册代码的注册成功后登陆注销,弄完帐户后再恢复。就下面这行

 await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

需求1解决,需求2搜了点文章,解决这个问题的同时让我对MVC三个层次的工作方式又理解了一些。

解决办法:

  1. 让注册页必须由一定权限的人登陆,无权限的人会提示登陆,登陆完再验证权限。在AccountController.cs的Register部分注销匿名,添加Roles控制,即只允许Admins用户访问这个页面。
  2.         //
            // POST: /Account/Register
            [HttpPost]
            //[AllowAnonymous]
            [Authorize(Roles = "Admins")]
            [ValidateAntiForgeryToken]
            public async Task<ActionResult> Register(RegisterViewModel model)

    这时候如果调试,会发现所有人都无法访问这个界面,会提示你登陆,然后就看不到了。查了下Account下的几个代码,好像没有集成用户组管理的页面和代码。于是在数据库里手动添加。
    在数据库的AspNetRoles表里添加ID为1,Name为Admins的条目,以及ID为2,Name为Users的条目。
    在数据库的AspNetUserRoles表里,将刚注册的用户的ID(Hash值)添加到这里的UserID,RoleID为1,就可以设定这个用户的Roles为Admin了。添加的其他用户可以手动分配为2(Users),或者像我一样没需求的,可以不分配。

通过这个问题的搜索学习,还了解到了一些MVC的设计思路,之前自己瞎玩的时候搞得一团糟,几乎把所有的代码都放到了View层,虽然也尝试把数据结构放到了Models,但是还是耦合到一团球。

我之前理解路由(当然是错误的理解),Control层只是起到转发Action的作用,并实现一些数据处理,而且这些数据处理都是手写的,但是在研究注册页的注册按钮如何工作时,我凌乱了,半天没理解怎么弄的,找到了一个stackoverflow的高分回答,解释了一下Model和Control的Binding关系,读了两遍,再回去看代码,果然就明白了。

模型基本上只提供了一个数据结构,而且基本只是数据的值,不包含函数(方法),View在提交Post的时候,调用的是同一个路由,所以开始看的时候莫名的觉得这个页面既显示注册界面,又完成了注册功能。然后找到Controller的时候,虽然明白了Controller如何完成功能,但是又不明白这些数据结构是如何传递的。相对的,也不明白Model是如何在这里面起作用的。

这些能活下来的框架和设计,都是相对简单且实用的,理解起来其实并不是太困难,但是需要一些点拨和经验。

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注