Nancy之Forms authentication的簡單使用


一、前言

想必大家或多或少都聽過微軟推出的ASP.NET Identity技術,可以簡單的認為就是一種授權的實現

很巧的是,Nancy中也有與之相類似的技術Authentication,這兩者之間都用到了一些相通的安全技術

(我沒有去看ASP.NET Identity的內部實現,是從它的簡單用法中判斷的)

正式開始介紹之前先推薦幾篇ASP.NET Identity的好文章

r01cn 的 ASP.NET Identity系列教程(目錄)

騰飛(Jesse) 的 MVC5 - ASP.NET Identity登錄原理 - Claims-based認證和OWIN

 

好了,下面還是用demo的形式來介紹怎么簡單使用Forms authentication吧

二、簡單使用

1)、新建一個空的asp.net項目

2)、通過NuGet安裝相應的包

1       Install-Package Nancy
2      Install-Package Nancy.Hosting.Aspnet
3       Install-Package Nancy.Authentication.Forms
4       Install-Package Dapper

由於用到了數據庫訪問,所以還安裝了Dapper

 

3)、建立數據表

 1 CREATE TABLE [dbo].[SystemUser](
 2     [SystemUserId] [uniqueidentifier] NOT NULL,
 3     [SystemUserName] [nvarchar](50) NOT NULL,
 4     [SystemUserPassword] [nvarchar](50) NOT NULL,
 5  CONSTRAINT [PK_SystemUser] PRIMARY KEY CLUSTERED 
 6 (
 7     [SystemUserId] ASC
 8 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 9 ) ON [PRIMARY]
10 GO

 

同時像表中插入兩條數據

1 INSERT INTO [dbo].[SystemUser]([SystemUserId],[SystemUserName],[SystemUserPassword])
2 VALUES(newid(),'catcher','123')
3 INSERT INTO [dbo].[SystemUser]([SystemUserId],[SystemUserName],[SystemUserPassword])
4 VALUES(newid(),'admin','123')

 

注:由於是演示,所以密碼沒有進行加密處理

4)、建立相應的文件夾

  Models用於存放模型

  Modules用於存放相應的操作

  Views用於存放視圖

 

5)、編寫模型 SystemUser.cs

1     public class SystemUser
2     {
3         public Guid SystemUserId { get; set; }
4         public string SystemUserName { get; set; }
5         public string SystemUserPassword { get; set; }
6     }   

6)、編寫HomeModule.cs

 1 using Dapper;
 2 using Nancy;
 3 using Nancy.Authentication.Forms;
 4 using Nancy.ModelBinding;
 5 using NancyDemoForFormsauthentication.Models;
 6 using System.Data;
 7 using System.Data.SqlClient;
 8 using System.Linq;
 9 namespace NancyDemoForFormsauthentication.Modules
10 {
11     public class HomeModule : NancyModule
12     {
13         public HomeModule()
14         {
15             Get["/"] = _ =>
16             {
17                 return View["index"];
18             };
19             Get["/login"] = _ =>
20             {
21                 return View["login"];
22             };
23             Post["/login"] = _ =>
24             {
25                 var loginUser = this.Bind<SystemUser>();
26                 SystemUser user = GetValidUser(loginUser.SystemUserName, loginUser.SystemUserPassword);
27                 if (user == null)
28                 {
29                     return Response.AsText("出錯了", "text/html;charset=UTF-8");
30                 }
31                 return this.LoginAndRedirect(user.SystemUserId, fallbackRedirectUrl: "/secure");
32             };
33         }
34         private readonly string sqlconnection =
35                "Data Source=127.0.0.1;Initial Catalog=NancyDemo;User Id=sa;Password=dream_time1314;";
36         private SqlConnection OpenConnection()
37         {
38             SqlConnection connection = new SqlConnection(sqlconnection);
39             connection.Open();
40             return connection;
41         }
42         private SystemUser GetValidUser(string name, string pwd)
43         {
44             using (IDbConnection conn = OpenConnection())
45             {
46                 const string query = "select * from SystemUser where SystemUserName=@SystemUserName and SystemUserPassword=@SystemUserPassword";
47                 return conn.Query<SystemUser>(query, new { SystemUserName = name, SystemUserPassword = pwd }).SingleOrDefault();
48             }
49         }
50     }
51 }  

 

其中,登錄的post方法中用到了 LoginAndRedirect 這個靜態方法

這個方法位於ModuleExtensions.cs中,返回值是Response類型的

1         public static Response LoginAndRedirect(this INancyModule module, Guid userIdentifier, DateTime? cookieExpiry = null, string fallbackRedirectUrl = "/")
2         {
3             return FormsAuthentication.UserLoggedInRedirectResponse(module.Context, userIdentifier, cookieExpiry, fallbackRedirectUrl);
4         }

看方法名都能知道這個是用來干什么的!

 

還有Response.AsText后面的第二個參數可以讓中文不亂碼!!

7)、編寫相應的視圖

index.html

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title></title>
 5     <meta charset="utf-8" />
 6 </head>
 7 <body>
 8     <h2>Nancy之基於Forms authentication的簡單使用</h2>
 9     <p>訪問需要權限的頁面</p>
10     <a href="/secure">secure</a>
11 </body>
12 </html>

login.html

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title></title>
 5     <meta charset="utf-8" />
 6 </head>
 7 <body>
 8     <form method="post" action="/login">
 9         <label>姓名:</label><input type="text" name="SystemUserName" /><br />
10         <label>密碼:</label><input type="password" name="SystemUserPassword" /><br />
11         <input type="submit" />
12     </form>
13 </body>
14 </html>
 

8)、編寫SecureModule.cs

 1 using Nancy;
 2 using Nancy.Security;
 3 
 4 namespace NancyDemoForFormsauthentication.Modules
 5 {
 6     public class SecureModule : NancyModule
 7     {
 8         public SecureModule()
 9         {
10             this.RequiresAuthentication();
11             Get["/secure"] = _ =>
12             {
13                 return "Hello ," + this.Context.CurrentUser.UserName;
14             };
15         }
16     }
17 }  

 

 其中

 
1 this.RequiresAuthentication();

 

這句是關鍵!!表明需要驗證才能通過。位於Nancy.Security這個命名空間

通過驗證訪問后會打印出當前的用戶名稱。

 

9)、編寫Bootstraper.cs

 1 using Nancy;
 2 using Nancy.Authentication.Forms;
 3 using Nancy.TinyIoc;
 4 using Nancy.Bootstrapper;
 5 namespace NancyDemoForFormsauthentication
 6 {
 7     public class Bootstrapper : DefaultNancyBootstrapper
 8     {
 9         protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
10         {
11             base.ConfigureRequestContainer(container, context);
12             container.Register<IUserMapper, UserMapper>();
13         }
14         protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
15         {
16             base.RequestStartup(container, pipelines, context);
17             var formsAuthConfiguration = new FormsAuthenticationConfiguration
18             {
19                 RedirectUrl = "~/login",
20                 UserMapper = container.Resolve<IUserMapper>(),
21             };
22             FormsAuthentication.Enable(pipelines, formsAuthConfiguration);
23         }
24     }
25 }  

 

這里是至關重要的一步!!!

要在RequestStartup中啟用我們的FormsAuthentication!!

同時我們還要配置FormsAuthenticationConfiguration

注冊了UserMapper,所以我們接下來就是實現UserMapper

 

10)、編寫UserMapper.cs

 1 using Dapper;
 2 using Nancy;
 3 using Nancy.Authentication.Forms;
 4 using Nancy.Security;
 5 using NancyDemoForFormsauthentication.Models;
 6 using System;
 7 using System.Data;
 8 using System.Data.SqlClient;
 9 using System.Linq;
10 namespace NancyDemoForFormsauthentication
11 {
12     public class UserMapper : IUserMapper
13     {
14         public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
15         {
16             using (IDbConnection conn = OpenConnection())
17             {
18                 const string query = "select * from SystemUser where SystemUserId=@SystemUserId";
19                 var user = conn.Query<SystemUser>(query, new { SystemUserId = identifier }).SingleOrDefault();
20                 if (user == null)
21                 {
22                     return null;
23                 }
24                 else
25                 {
26                     return new UserIdentity
27                     {
28                         UserName = user.SystemUserName,
29                         Claims = new[] { "SystemUser"}
30                     };
31                 }
32             }
33         }
34         private readonly string sqlconnection =
35                 "Data Source=127.0.0.1;Initial Catalog=NancyDemo;User Id=sa;Password=dream_time1314;";
36         private SqlConnection OpenConnection()
37         {
38             SqlConnection connection = new SqlConnection(sqlconnection);
39             connection.Open();
40             return connection;
41         }
42     }
43 }  

 

UserMapper必須要實現IUserMapper這個接口!同時返回一個實現IUserIdentity接口的對象。

 

11)、編寫UserIdentity.cs

 1 using Nancy.Security;
 2 using System.Collections.Generic;
 3 namespace NancyDemoForFormsauthentication
 4 {
 5     public class UserIdentity : IUserIdentity
 6     {
 7         public string UserName { get; set; }
 8         public IEnumerable<string> Claims { get; set; }
 9     }
10 }  

 

到這里所有的工作都已經做完了,下面就是看看效果了

我們點擊 secure鏈接,發現自動跳轉到登錄界面了!!

 

 我們輸入用戶名和密碼

 

登錄成功,並返回到secure頁面了! 

 

當我們輸入錯誤的用戶名和密碼時

 

 

最后是本次示例代碼:

https://github.com/hwqdt/Demos/tree/master/src/NancyDemoForFormsauthentication

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM