惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
C
Cybersecurity and Infrastructure Security Agency CISA
P
Proofpoint News Feed
Security Latest
Security Latest
P
Privacy International News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AI
AI
Cisco Talos Blog
Cisco Talos Blog
K
Kaspersky official blog
S
Secure Thoughts
PCI Perspectives
PCI Perspectives
Simon Willison's Weblog
Simon Willison's Weblog
D
DataBreaches.Net
GbyAI
GbyAI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
罗磊的独立博客
V
Visual Studio Blog
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
IT之家
IT之家
V
V2EX
Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tenable Blog
T
Threat Research - Cisco Blogs
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
S
Security @ Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
Lohrmann on Cybersecurity
F
Full Disclosure
H
Help Net Security
博客园 - Franky
Stack Overflow Blog
Stack Overflow Blog
N
Netflix TechBlog - Medium
Engineering at Meta
Engineering at Meta
A
Arctic Wolf
O
OpenAI News
S
Securelist

博客园 - goodbaby

辞职了 爱上无聊 读程序有感 把网通的网关接口程序重写了 深深陷入困境 我的技术和观点 我的AOP初步 静态和动态控件回递数据的处理差别 membership and roleship 我的asp.net 2.0初体验 一点技术,一点生活 简单体验多层应用 基于服务的架构 变化,感触 又可以进自己的blog了 浅谈asp.net UI 浅谈验证码 浅谈数据库里的自引用 简单的URL重写
浅谈基于角色的安全
goodbaby · 2004-11-25 · via 博客园 - goodbaby
 

     基于角色的安全在web应用有广泛的应用,在.net中对角色安全的支持分为三中

      1:基于Windows的身份验证

      2:基于表单的身份验证

      3:基于Passport的身份验证

 简单说一下第一种和第三种,基于Windows的身份验证是把安全交给Windows的安全

子系统,依靠域服务器和IIS,当一个请求到达时,IIS首先截获,请求域服务器,进行身份验证,生成访问钥匙,然后严格按照ACL(Access Control List),执行相应的权限。基于Windows的角色安全是用在局域网的(Intranet)。基于Web(Internet)应用拥有大量用户的程序来说,维护一个庞大的ACL是不现实的,所以要使用基于表单的身份验证和基于Passport的身份验证,Passport的身份验证是MS提供的一个用来赚钱的服务,你要去订阅,他提供了很高的安全性和可跨站点的访问。基于表单的身份验证是最多的吧,我简单研究了一下,也对他进行了简单的实现。

      有的解决方案是Context.User=new GenericPrinciple(“”,角色数组);但是这不能够解决权限问题(我想了很久),所以需要实现一个IPrinciple接口扩充负责者的功能。好了,先看一下数据库的设计:

一个RoleAuthentication_Account表,包括UserID,UserFriendName,UserName,Password字段用来存储用户信息,不用多说。

一个RoleAuthentication_Role表,包括RoleID,Description

一个RoleAuthentication_Permission,包括PermissionId,Description,

一个RoleAuthentication_AccountRole, RoleAuthentication_RolePermission,很简单完成多对多的应射。

好了接下来数据服务的程序:

RoleAuthenticationDAL.cs

using System;

using System.Data;

using System.Data.SqlClient;

using System.Collections;

using System.Text;

using System.Security;

using System.Security.Cryptography;

namespace RoleAuthenticationDataAccessLayer

{

     /// <summary>

     /// Class1 的摘要说明。

     /// </summary>

     public class Account

     {

         public Account()

         {

              //

              // TODO: 在此处添加构造函数逻辑

              //

         }

         public DataRow getUserInfo(int UserID)

         {

              SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.Int) };

              parameters[0].Value = UserID;

            DataSet ds=DataAccessHelper.EexcuteDataSet(DataAccessHelper.ConStr,CommandType.StoredProcedure,"getUserInfo",parameters);

              return ds.Tables[0].Rows[0];

         }

         public ArrayList getUserRole(int UserID)

         {

              ArrayList role=new ArrayList();

              SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.Int) };

              parameters[0].Value = UserID;

              SqlDataReader dr = DataAccessHelper.ExecuteReader(DataAccessHelper.ConStr,CommandType.StoredProcedure,"getUserRole",parameters);

              while(dr.Read())

              {

                   role.Add(dr.GetInt32(0));

              }

              dr.Close();

              return role;

         }

         public ArrayList getUserPermission(int UserID)

         {

              ArrayList role=new ArrayList();

              SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.Int) };

              parameters[0].Value = UserID;

              SqlDataReader dr = DataAccessHelper.ExecuteReader(DataAccessHelper.ConStr,CommandType.StoredProcedure,"getUserPermission",parameters);

              while(dr.Read())

              {

                   role.Add(dr.GetInt32(0));

              }

              dr.Close();

              return role;

         }

         public int Login(string UserName,string Password)

         {

              for(int i=0;i<15-UserName.Length;i++)

              {

                   UserName+=" ";

              }

              byte[] pass=EncryptPassword(Password);

              SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.Int),new SqlParameter("@UserName", SqlDbType.Char),new SqlParameter("@UserPassword", SqlDbType.VarBinary) };

              parameters[0].Direction=ParameterDirection.Output;

              parameters[1].Value = UserName;

            parameters[2].Value=pass;

              int result=DataAccessHelper.RExecutNonQuery(DataAccessHelper.ConStr,CommandType.StoredProcedure,"Login",parameters);

              if(result>0)

              {

                   return result;

              }

              else

              {

                   return -1;

              }

         }

         public static byte[] EncryptPassword(string password)

         {

              UnicodeEncoding encoding = new UnicodeEncoding();

              byte[] hashBytes = encoding.GetBytes( password );

              // compute SHA-1 hash.

              SHA1 sha1 = new SHA1CryptoServiceProvider();

              byte[] cryptPassword = sha1.ComputeHash ( hashBytes );

              return cryptPassword;

         }

         public bool AddUser(string UserName,string UserFriendName,string Password)

         {

              for(int i=0;i<15-UserName.Length;i++)

              {

                   UserName+=" ";

              }

              byte[] pass=EncryptPassword(Password);

              SqlParameter[] parameters = { new SqlParameter("@UserName", SqlDbType.Char),new SqlParameter("@UserPassword", SqlDbType.VarBinary,20),new SqlParameter("@UserFriendName", SqlDbType.VarChar,50) };

              parameters[0].Value = UserName;

              parameters[1].Value=pass;

              parameters[2].Value=UserFriendName;

              if(DataAccessHelper.ExecutNonQuery(DataAccessHelper.ConStr,CommandType.StoredProcedure,"AddUser",parameters)>0)

              {

                   return true;

              }

              else

              {

                   return false;

              }

         }

         public bool ContributeRoleForUser(int UserID,int RoleID)

         {

              SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.Int),new SqlParameter("@RoleID", SqlDbType.Int) };

              parameters[0].Value = UserID;

              parameters[1].Value=RoleID;

              if(DataAccessHelper.ExecutNonQuery(DataAccessHelper.ConStr,CommandType.StoredProcedure,"ContributeRoleForUser",parameters)>0)

              {

                   return true;

              }

              else

              {

                   return false;

              }

         }

     }

}

DataAccessHelper.cs这个简单的类是自己实现的在不知道有MSDataAccess之前

using System;

using System.Data;

using System.Data.SqlClient;

using System.Configuration;

namespace RoleAuthenticationDataAccessLayer

{

     /// <summary>

     /// DataAccessHelper 的摘要说明。

     /// </summary>

     public abstract class DataAccessHelper

     {

         public static readonly string ConStr="server=GOODBABY;database=PRRolesAuthentication;uid=sa;password=goodbaby";//ConfigurationSettings.AppSettings["ConnectionString"];

         public static int ExecutNonQuery(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

         {

              SqlCommand cmd=new SqlCommand();

              SqlConnection con=new SqlConnection(connString);

              PrepareCmd(cmd,con,cmdType,cmdText,cmdParms);

              try

              {

                   int result=cmd.ExecuteNonQuery();

                   cmd.Parameters.Clear();

                   return result;

              }

              catch(Exception ex)

              {

                   throw ex;

              }

              finally

              {

                   con.Close();

              }

         }

         public static int RExecutNonQuery(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

         {

              SqlCommand cmd=new SqlCommand();

              SqlConnection con=new SqlConnection(connString);

              PrepareCmd(cmd,con,cmdType,cmdText,cmdParms);

              try

              {

                   int result=-1;

                   cmd.ExecuteNonQuery();

                   if(cmd.Parameters[0].Value is DBNull)

                   {

                       return result;

                   }

                result=Convert.ToInt32(cmd.Parameters[0].Value);

                   cmd.Parameters.Clear();

                   return result;

              }

              catch(Exception ex)

              {

                   throw ex;

              }

              finally

              {

                   con.Close();

              }

         }

         public static SqlDataReader ExecuteReader(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

         {

              SqlCommand cmd=new SqlCommand();

              SqlConnection con=new SqlConnection(connString);

              PrepareCmd(cmd,con,cmdType,cmdText,cmdParms);

              try

              {

                   return cmd.ExecuteReader(CommandBehavior.CloseConnection);

              }

              catch(SqlException ex1)

              {

                   throw ex1;

              }

         }

         public static DataSet EexcuteDataSet(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

         {

              SqlCommand cmd=new SqlCommand();

              SqlConnection con=new SqlConnection(connString);

              PrepareCmd(cmd,con,cmdType,cmdText,cmdParms);

              SqlDataAdapter dap=new SqlDataAdapter(cmd);

              try

              {

                   DataSet myDS=new DataSet();

                   dap.Fill(myDS);

                   return myDS;

              }

              catch(SqlException ex2)

              {

                   throw ex2;

              }

              finally

              {

                   con.Close();

              }

         }

         private static void PrepareCmd(SqlCommand cmd, SqlConnection conn, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)

         {

              if (conn.State != ConnectionState.Open)

                   conn.Open();

            cmd.Connection = conn;

              cmd.CommandText = cmdText;

              cmd.CommandType=cmdType;

              if (cmdParms != null)

              {

                   foreach(SqlParameter SqlPar in cmdParms)

                   {

                       cmd.Parameters.Add(SqlPar);

                   }

              }

         }

     }

}

BL中实现了IPrinciple,IIdentity

using System;

using System.Security.Principal;

using System.Collections;

using RoleAuthenticationDataAccessLayer;

namespace RolsesAuthenticationBL

{

     /// <summary>

     /// Class1 的摘要说明。

     /// </summary>

     public class MyPrinciple:IPrincipal

     {

         protected IIdentity  identity;

         protected ArrayList permissionList;

         protected ArrayList roleList;

         public MyPrinciple()

         {

              //

              // TODO: 在此处添加构造函数逻辑

              //

         }

        //use DataAccessLayer'user class to set Attributes and use UserID to constructe a identity object

         public MyPrinciple(int UserID)

         {

            Account account=new Account();

              roleList=account.getUserRole(UserID);

             permissionList=account.getUserPermission(UserID);

              identity=new MyIdentity(UserID);

         }

         public IIdentity Identity

         {

              get

              {

                   return identity;

              }

              set

              {

                   identity = value;

              }

         }

         public bool IsInRole(string role)

         {

              return roleList.Contains( role );

         }

         public bool HasPermission( int permissionID )

         {

              return permissionList.Contains( permissionID );

         }

         public ArrayList Permissions

         {

              get

              {

                   return permissionList;

              }

         }

         public ArrayList Roles

         {

              get

              {

                   return roleList;

              }

         }

     }

}

MyIdentity.cs

using System;

using System.Security.Principal;

using RoleAuthenticationDataAccessLayer;

using System.Data;

namespace RolsesAuthenticationBL

{

     /// <summary>

     /// MyIdentity 的摘要说明。

     /// </summary>

     ///

     public class MyIdentity:IIdentity

     {

         private string _Name;

         private int    _UserID;

         private string _FriendName;

        private byte[] _Password;

         public MyIdentity()

         {

              //

              // TODO: 在此处添加构造函数逻辑

              //

         }

        //use userid for set attribute use DataAccessLayer'user class

         public MyIdentity(int UserID)

         {

              _UserID=UserID;

            Account account=new Account();

              DataRow datarow=account.getUserInfo(UserID);

              _Name=(string)datarow["UserName"];

            _FriendName=(string)datarow["UserFriendName"];

              _Password=(byte[])datarow["UserPassword"];

         }

         public bool IsAuthenticated

         {

              get

              {

                   return true;

              }

         }

         public string AuthenticationType

         {

              get

              {

                   return "MyCustom";

              }

         }

         public string Name

         {

              get

              {

                   return _Name;

              }

         }

         public int UserID

         {

              get

              {

                   return _UserID;

              }

         }

         public string FriendName

         {

              get

              {

                   return _FriendName;

              }

         }

         public byte[] Password

         {

              get

              {

                   return _Password;

              }

         }

     }

}

User封装验证,由于关注的是实现角色验证这个类没什么功能。

最后在SignIn.aspx中登陆后,在testpage.aspx中的Page_Load()中重新为User指定Principle

if(Context.User.Identity.IsAuthenticated)

              {

                   status.Text="I am Authenticationed";

                   if(!(Context.User is MyPrinciple))

                   {

                       status.Text=status.Text+"  I am not MyPrincipleType!";

                       Context.User=new MyPrinciple(int.Parse(User.Identity.Name));

                   }

              }

              else

              {

                   Response.Redirect("SignIn.aspx");

              }

也可以在Globle.asax中为设置User,不要在Application_BeginRequest()中,试了一下是不行的,原因很简单,请你想一下,在验证和授权中吧。好了用一个Button来测试一下,对一个需要权限ID2的操作进行验证,

private void Button1_Click(object sender, System.EventArgs e)

         {

              status.Text=User.GetType().ToString();

              if(((MyPrinciple)User).HasPermission(2))

              {

                   status.Text=status.Text+" and you have the permission";

              }

              else

              {

                   status.Text="sorry you hava'not the permission";

              }

         }

OK结果符合了预期的效果。

图:

好了,入门学习,水平不高,希望大家指正。