1. 程式人生 > 實用技巧 >Authentication and authorization (one)

Authentication and authorization (one)

前言

.net core web並不是一個非常新的架構,很多文章提及到認證與授權這個過程,但是一般都會提及到裡面的方法怎麼用的,而不是模擬一個怎樣的過程,所以我打算記錄自己的理解。
什麼是認證?我們大學畢業有學士證書和畢業證書,來證明你是一個學士。
什麼是授權,比如說你被認證是我的朋友後,你可以拿著這個身份,可以進入我的朋友圈看動態。
那麼.net core 的認證與授權是一個什麼樣的過程,在這裡提出簡單模式是我給你頒發了證書,證明了你的身份,然後呢,你可以拿到你的身份卡之後,你要經過驗證,得到授權,然後進入中華人民共和國,就是這個過程。
正文部分均為我的理解,可能存在誤差,如果不對請指正。

正文

public class HomeController : Controller
{
	public IActionResult Index()
	{
		return View();
	}

	[Authorize]
	public IActionResult Secret()
	{
		return View();
	}

	public IActionResult Authenticate()
	{
		return RedirectToAction("Index");
	}
}

我有一個control,裡面action有index ,Secret ,Authenticate。
index View:

<h1>Home Page</h1>

Secret View:

<h1>Secret</h1>

然後我們訪問
https://localhost:44350/Home/Index
效果:

如我意料,完全ok的。
然後訪問:
https://localhost:44350/Home/Secret
出現了錯誤:

給了非常詳細的提示,未指定認證方案。
我們看到,唯一和index 不同的是加入了Authorize這個屬性標籤,這是個授權的意思,但是提示給我們的是我們沒有認證。
好的,說明吧授權之前要認證,要識別出身份,現實中也是這樣,能證明你的只有你的身份證,沒有身份證我怎麼給你授權。
好的,那麼就新增認證過程:
認證有非常多種,這裡就以cookie來簡單的介紹。

public void ConfigureServices(IServiceCollection services)
{
	services.Configure<CookiePolicyOptions>(options =>
	{
		// This lambda determines whether user consent for non-essential cookies is needed for a given request.
		options.CheckConsentNeeded = context => true;
		options.MinimumSameSitePolicy = SameSiteMode.None;
	});

	services.AddAuthentication("CookieAuth").AddCookie("CookieAuth", config =>
	{
		config.Cookie.Name = "Cook.Name";
		config.LoginPath = "/Home/Authenticate";
	});

	services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

我添加了一段:

services.AddAuthentication("CookieAuth").AddCookie("CookieAuth", config =>
{
	config.Cookie.Name = "Cook.Name";
	config.LoginPath = "/Home/Authenticate";
});

如果沒有cookie認證,那麼就跳轉到/Home/Authenticate 去認證。
在/Home/Authenticate 下面我沒有做任何事情,僅僅是去跳轉到/Home/Index
那麼正常情況下,是會跳轉到/Home/Index。
是的,當我們訪問:
https://localhost:44350/Home/Secret
看到的效果是:
https://localhost:44350/Home/Index
這是如我們所料的,那麼我們就在/Home/Authenticate做一些事情,比如說頒發證書。
好的,那我們就在/home/Authenticate 中頒發證書:

public IActionResult Authenticate()
{
	var SchoolClaims = new List<Claim>()
	{
		new Claim(ClaimTypes.Name,"Jack"),
		new Claim(ClaimTypes.Email,"[email protected]")
	};

	var LicensClaims = new List<Claim>()
	{
		new Claim(ClaimTypes.Name,"Jack.li"),
		new Claim(ClaimTypes.Email,"[email protected]"),
		new Claim("begin","2000.10.1")
	};
	var SchoolIdentity = new ClaimsIdentity(SchoolClaims,"Student Identity");
	var CarManagerIdentity = new ClaimsIdentity(LicensClaims, "Licens Identity");
	var userPrincipal = new ClaimsPrincipal(new[] { SchoolIdentity, CarManagerIdentity });
	
	HttpContext.SignInAsync(userPrincipal);
	return RedirectToAction("Index");
}

看下程式碼順序:
我們建立了List(),這些是什麼呢?
就是我們的資訊。
比如我們駕駛證上有我們的名字,編號。
然後通過:
new ClaimsIdentity(LicensClaims, "Licens Identity");
生成了一個identity,也就是產生了一張證書,這種證書叫做:Licens Identity,當然我們隨意名字。
var userPrincipal = new ClaimsPrincipal(new[] { SchoolIdentity, CarManagerIdentity });
我們一生中有身份證,學位證,駕駛證,這麼多證書是不是需要一個管理的呢?ClaimsPrincipal就是用來管理證書的。
HttpContext.SignInAsync(userPrincipal); 就會產生證書並且輸入到前臺。

請看,對這個cooke.name 是不是特別熟悉呢?就是我們啟用了cookie 認證,如果忘記了請往上看。
但是訪問:
https://localhost:44350/Home/Secret
看到的效果還是:
https://localhost:44350/Home/Index
這是為啥呢?不是認證了嗎?
其實:

services.AddAuthentication("CookieAuth").AddCookie("CookieAuth", config =>
{
	config.Cookie.Name = "Cook.Name";
	config.LoginPath = "/Home/Authenticate";
});

和:

public IActionResult Authenticate()
{
	var SchoolClaims = new List<Claim>()
	{
		new Claim(ClaimTypes.Name,"Jack"),
		new Claim(ClaimTypes.Email,"[email protected]")
	};

	var LicensClaims = new List<Claim>()
	{
		new Claim(ClaimTypes.Name,"Jack.li"),
		new Claim(ClaimTypes.Email,"[email protected]"),
		new Claim("begin","2000.10.1")
	};
	var SchoolIdentity = new ClaimsIdentity(SchoolClaims,"Student Identity");
	var CarManagerIdentity = new ClaimsIdentity(LicensClaims, "Licens Identity");
	var userPrincipal = new ClaimsPrincipal(new[] { SchoolIdentity, CarManagerIdentity });
	
	HttpContext.SignInAsync(userPrincipal);
	return RedirectToAction("Index");
}

重新來看這兩個的關係。
得到的錯誤是沒有一個認證的方案,然後寫了添加了cookie驗證,然後下面的是去實現把證書裝配到cookie中。
驗證機制生效了,證書也到前臺了。最大可能的可能就是沒有去拿證書,或者說證書機制除了驗證其他的步驟都沒有,也就是沒有啟動證書驗證這套流程。
需要加上在:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	else
	{
		app.UseExceptionHandler("/Home/Error");
		// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
		app.UseHsts();
	}

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

啟動身份認證:

app.UseAuthentication();


也就是我們說:

services.AddAuthentication("CookieAuth").AddCookie("CookieAuth", config =>
{
	config.Cookie.Name = "Cook.Name";
	config.LoginPath = "/Home/Authenticate";
});

是去驗證證書,而app.UseAuthentication();是去拿證書,整理證書,沒有拿到證書相當於沒有證書,所以一直不通過。
然後在.net core 3.0中,分的更細,還有問我們是否啟動授權。而2.0 app.UseAuthentication()就可以了。

總結

以上只是個人的理解,在後續介紹如何與資料庫建立聯絡。