用了很长一段时间了, 但是一直没有做过任何笔记,感觉 identity 太多东西要写了, 提不起劲. 但是时间一久很多东西都记不清了.

还是写一轮吧. 加深记忆.

这是 0-1 的笔记, 会写好多篇. 写的时候是没有提前设计流程, 所以如果你把它当教程来看是不太妥当的,要读就必须一篇一篇顺着读,间中还会有错误和修正, 请小心.

identity 就是做登入授权的一个架构, asp.net core 自带的. 因为大部分项目都会需要有登入授权机制.

identity server 之后才会提到.

虽然 identity 有自带的 ui 模板,但是为了比较清楚我们还是从一个空白的项目开始吧.

开启 vs 2019 创建一个 razor page 项目.

首先, 我们来做一些基本 setup. identity 需要有一个 sql 储存, 我们就使用 ef core + local sql server (vs 2019 自带) 吧.

如果你不熟悉 ef core 可以看这里 https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-2.2

先创建一个 DbContext 并继承 IdentityDbContext

namespace Project.Entity
{
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{ }
}
}

IdentityDbContext 封装了所有 identity 需要的 tables, 比如 user, role, claim 等等...

添加 default connection string config 在 appsettings.json.

 "ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=identity;Trusted_Connection=True;MultipleActiveResultSets=true"
}

添加 service 到 startup.cs

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")
)
);

数据库弄好了以后我们来弄 identity service

identity 给了我们一个 AddDefaultIdentity 的便利

services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();

但是这个是配合 default ui 的, 我们直接用比较底层的功能 .

参考源码 https://github.com/aspnet/AspNetCore/blob/release/2.2/src/Identity/UI/src/IdentityServiceCollectionUIExtensions.cs#L47-L63

services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { }); services.AddIdentityCore<IdentityUser>(o =>
{
o.Stores.MaxLengthForKeys = ;
})
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>(); services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/Login";
});

从源码抄过来, 省略掉 .AddDefaultUI() 就可以了.

这里还多了一个 ConfigureApplicationCookie, 我设定了一个登入页面路径, 当用户访问一个权限页面的时候就会被自动跳转到登入页面.

identtiy 还可以配置很多 config, 之后才说.

到这里, services 算是弄好了. 我们来弄 AppConfig, 添加 app.UseAuthentication() 就可以了

app.UseCookiePolicy();

app.UseAuthentication(); // 加入这个

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

startup.cs 完成. 我们现在去创建 2 个 razor page. 一个 About, 一个 Login

然后在 About.cshtml.cs 里做一个权限访问.

[Authorize]
public class AboutModel : PageModel
{
public void OnGet()
{ }
}

在到 home page 做一个 <a> 访问 about page

home page
<a asp-page="About" >about</a>

当我们访问 about 时, 就会被跳转到 login 页面了。

目前我们还没有任何账号可以登入,必须先有一个 register 的功能.

这时就会用到数据库了. 刚才我们做了配置但是并还没有生成数据库

我们使用 ef core migrations 来完成这个事情, 如果你不熟悉这个请先看这里

https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/

运行 command

dotnet ef migrations add init

dotnet ef database update

搞定!

接下来就是做一个 register form 我们直接在 login page 里头做就好了.

Register form
<form asp-page="Login" asp-page-handler="Login">
<input type="text" name="username" placeholder="username">
<input type="password" name="password" placeholder="password">
<button type="submit">Login</button>
</form>

同时在  Login.cshtml.cs 也做一个 handler

public class LoginInputModel
{
public string username { get; set; }
public string password { get; set; }
} [BindProperty]
public LoginInputModel LoginData { get; set; } public async Task OnPostLoginAsync([FromServices] UserManager<IdentityUser> userManager)
{
var user = new IdentityUser
{
UserName = LoginData.username
};
var reuslt = await userManager.CreateAsync(user, LoginData.password);
if (reuslt.Succeeded)
{ }
}

使用 userManager service 来替我们服务. 这是 identity 封装的服务.

这个小功能里头做了不少事儿...

比如 :

检查 password 格式 (不能少于 6 个字啦... 要有大写啦... 等等等, 这个我们是可以配置的, 等下会讲)

检查 username 格式对不对 (有些时候 username 不能包含默写字符串或者符号等, 这个也是可以配置的, 等下讲)

检查 username duplicate,或者 email duplicate (username 一定是 unique, email 则可以配置要不要 unique,之后会讲)

hash password, 我们都知道用户的 password 不可以明文保存在数据库 ( 如果你不知道可以上网搜搜, 比如 https://www.douban.com/group/topic/26022844/ )

这里 hash password 就涉及到 md5, sha256, 盐等等密码学的知识了. identity 就是为我们处理了这些事儿, 省心吧.

最后就是入库啦.

如果你按照目前的代码运行,并且输入

username = "``"

password = "``"

result 会出现 error, 因为 identity 默认对 password 蛮严格的,还有 username 也是有指定的字符串.

我们现在就去调整它. 当 startup.cs 的 service 调整 options

如果你对 options 的使用不熟悉,可以看这里 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.2

services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequiredLength = ;
options.Password.RequiredUniqueChars = ; // User settings.
options.User.AllowedUserNameCharacters = null; // 默认是 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; null 表示啥都行
options.User.RequireUniqueEmail = false;
});

这样就完全没有限制了.

有人喜欢无拘无束,有人不喜欢.

如果我们反而嫌 identity 的 password valid 还不够多呢?

比如, 我要求, password 不可以和 username 相等. 这个怎么实现呢 ?

identity 为我们开放了扩展

首先写一个 validator class 实现接口 IPasswordValidator

public class MyPasswordValidator : IPasswordValidator<IdentityUser>
{
public Task<IdentityResult> ValidateAsync(UserManager<IdentityUser> manager, IdentityUser user, string password)
{
if (user.UserName.Equals(password, StringComparison.OrdinalIgnoreCase))
{
var result = IdentityResult.Failed(new IdentityError
{
Code = "PasswordSameAsUsername",
Description = "password can't same as username."
});
return Task.FromResult(result);
}
return Task.FromResult(IdentityResult.Success);
}
}

里面可以使用依赖注入获取我们要的任何服务, 如果你的验证需要用数据库, 用 HttpClient 都是可以的.

然后呢,我们把这个 validator 添加进 identity 里头, 到 startup.cs 的 service 里弄

services.AddIdentityCore<IdentityUser>(o =>
{
o.Stores.MaxLengthForKeys = ;
})
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddPasswordValidator<MyPasswordValidator>(); // 加这个

如果有很多个, 也可以一个一个加进去. 并没有限制多少个 validator.  在源码中可以看到, identity 会把所有 validator for loop 来执行 ValidateAsync

user validator 也是类似的实现手法,

创建一个 UserValidator 里面写逻辑

public class MyUserValidator : IUserValidator<IdentityUser>
{
public Task<IdentityResult> ValidateAsync(UserManager<IdentityUser> manager, IdentityUser user)
{
if (!user.UserName.EndsWith("stooges.com.my"))
{
var result = IdentityResult.Failed(new IdentityError
{
Code = "UsernameNotEndsWithStoogesDomain",
Description = "username must ends with stooges.com.my"
});
return Task.FromResult(result);
}
return Task.FromResult(IdentityResult.Success);
}
}

加入 startup.cs service

services.AddIdentityCore<IdentityUser>(o =>
{
o.Stores.MaxLengthForKeys = ;
})
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddPasswordValidator<MyPasswordValidator>()
.AddUserValidator<MyUserValidator>(); // 加这个

搞定 !

这篇总结与回顾 :

- 空白的 razor page

- ef core with identity DbContext setup

- identity setup

- authorize page (about) and login page

- register create user

- password validator

- user validator

github : https://github.com/keatkeat87/aspnetcore-identity 
我的 commit 是依据一篇一篇 turorial 写的,可以 checkout 回去观察。

Asp.net core Identity + identity server + angular 学习笔记 (第一篇)的更多相关文章

  1. Asp.net core Identity + identity server + angular 学习笔记 (第二篇)

    先纠正一下第一篇的的错误. 在 Login.cshtml 和 Login.cshtml.cs 里, 本来应该是 Register 我却写成 Login . cshtml 修改部分 <form a ...

  2. ActionBarSherlock学习笔记 第一篇——部署

    ActionBarSherlock学习笔记 第一篇--部署          ActionBarSherlock是JakeWharton编写的一个开源框架,使用这个框架,可以实现在所有的Android ...

  3. Asp.net core Identity + identity server + angular 学习笔记 (第三篇)

    register -> login 讲了 我们来讲讲 forgot password -> reset password  和 change password 吧 先来 forgot pa ...

  4. ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探

    前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...

  5. Asp.net core Identity + identity server + angular 学习笔记 (第五篇)

    ABAC (Attribute Based Access Control) 基于属性得权限管理. 属性就是 key and value 表达力非常得强. 我们可以用 key = role value ...

  6. Asp.net core Identity + identity server + angular 学习笔记 (第四篇)

    来说说 RBAC (role based access control) 这是目前全世界最通用的权限管理机制, 当然使用率高并不是说它最好. 它也有很多局限的. 我们来讲讲最简单的 role base ...

  7. Asp.Net Core + Dapper + Repository 模式 + TDD 学习笔记

    0x00 前言 之前一直使用的是 EF ,做了一个简单的小项目后发现 EF 的表现并不是很好,就比如联表查询,因为现在的 EF Core 也没有啥好用的分析工具,所以也不知道该怎么写 Linq 生成出 ...

  8. ASP.NET Core微服务 on K8S学习笔记(第一章:详解基本对象及服务发现)

    课程链接:http://video.jessetalk.cn/course/explore 良心课程,大家一起来学习哈! 任务1:课程介绍 任务2:Labels and Selectors 所有资源对 ...

  9. Node 之 Express 学习笔记 第一篇 安装

    最近由于工作不忙,正好闲暇时间学学基于 node 的 web开发框架. 现在关于web开发框架除了Express 还有新出的 KOA以及其它一些. 但是想想还是先从 Express 入手吧.因为比较成 ...

随机推荐

  1. 2019-oo-第二次总结

    这一单元是关于模拟电梯运行,考验多线程的一个单元,难度由简入入深,从多线程单部电梯,到优化,再到多线程多部电梯,难度一次次的提高. 一.多线程单部电梯(傻瓜调度) 1.设计策略 这一次我只额外的开了一 ...

  2. 如何正确对用户密码进行加密?转自https://blog.csdn.net/zhouyan8603/article/details/80473083

    本文介绍了对密码哈希加密的基础知识,以及什么是正确的加密方式.还介绍了常见的密码破解方法,给出了如何避免密码被破解的思路.相信读者阅读本文后,就会对密码的加密有一个正确的认识,并对密码正确进行加密措施 ...

  3. 浅谈Linux文件与目录权限

    作为一个程序员,在工作的过程中或多或少都会接触都Linux,那么对于权限这块肯定有所了解,今天有空想谈谈觉得比较绕的权限问题,即文件权限与目录权限 1.文件权限,对于文件权限这个是比较简单的,也很容易 ...

  4. Python文件操作中的方法:.write()换行

    active =Truewhile active: message =input("\nPlease input your name:\n") if message =='q': ...

  5. localStorage,sessionStorage和cookie的区别

    sessionStorage 和 localStorage 是HTML5 Web Storage API 提供的,可以方便的在web请求之间保存数据.有了本地数据,就可以避免数据在浏览器和服务器间不必 ...

  6. java.sql.SQLException: ORA-28000: the account is locked

    解决方式:参考博客https://blog.csdn.net/java280580332/article/details/70756533

  7. 【mac微信小助手】WeChatPlugin使用教程!

    微信小助手 mac版集微信防撤回和微信多开等诸多功能于一身,可以有效的阻止朋友微信撤回消息,还能开启无手机验证登录,再也不用每次登录扫码验证啦,非常方便!   wechatplugin mac版安装教 ...

  8. MATLAB R2018b Mac中文版安装教程

    MATLAB r2018b mac中文版是一款强大的可视化数学分析软件,专门用于在Mac上执行数值计算,编程和可视化任务时极大地提高您的工作效率.在MATLAB的帮助下,您可以分析数据,创建应用程序, ...

  9. docker环境下的测试

    docker作为容器常见用于快速部署,最近有个项目是基于docker的,总结一下docker的测试. 1.在主机中安装Docker: ubuntu安装:curl -s https://get.dock ...

  10. python开发环境配置和python源码打包生成exe可执行文件

    Windows下开发环境准备 1.分别安装:python2和python32.安装Python的集成工具:Anaconda3.安装Pycharm Pycharm设置 设置: File->Sett ...