浅析ASP.NET中的身份验证(不使用MembershipProvider)

Posted on 2008-05-07 17:37  Rock Wang  阅读(419)  评论(0编辑  收藏  举报

      ASP.NET2.0中提供的身份验证提供程序,对1.1中的验证机制进行了封装,并且和Login等控件结合使用,十分方便.但是它也有一些缺点:不易扩展,需要要一些特殊的表来存储这些信息等等.
      当然,你也可以通过重写Provider,不过这个工作量实在很大,而且重写后的Provider的复用性不高,下面我就介绍一下自己动手实现身份验证.
      我们分以下几种情况来讨论:
      1.用户名和密码存放在web.config中

 1<configuration>
 2  <system.web>
 3    <authentication mode="Forms">
 4      <credentials passwordFormat="Clear">
 5          <user name="Jim" password="Jim"/>
 6          <user name="Mike" password="Mike"/>
 7        </credentials>
 8    </authentication>
 9  </system.web>
10</configuration>

        protected void btnLogin_Click(object sender, EventArgs e)
        
{
            
     if (FormsAuthentication.Authenticate(username, password))
            
{
                FormsAuthentication.RedirectFromLoginPage(username, 
true);
                
            }

            
else
            
{
                Response.Write(
"<script>alert('Wrong username or password');</script>");
            }

        }
简单的几行代码,就实现了用户身份验证,其中用户密码可以采用Clear,SHA1,MD5三种格式,.NET自己会进行相应的转换,你只要在web.config中配置好,输入密码的时候还按最初的明码输入就行了.如下:
        <!--<credentials passwordFormat="Clear">
          <user name="Jim" password="Jim"/>
          <user name="Mike" password="Mike"/>
        </credentials>
-->
        
<credentials passwordFormat="SHA1">
          
<user name="Jim" password="7627F9952B9C378EDC494C5751804403E5973074"/>
          
<user name="Mike" password="D6AC022931A66A2BCC244DB91818EBEC76CE5E18"/>
        
</credentials>
        
<!--
        <credentials passwordFormat="MD5">
          <user name="Jim" password="D54B3C8FCD5BA07E47B400E69A287966"/>
          <user name="Mike" password="1B83D5DA74032B6A750EF12210642EEA"/>
        </credentials>
        
-->
    2.采用其他验证方法
    如果你的用户密码存在数据库中或者其他存储介绍中,就要自己写验证逻辑了
            if (密码正确)
            
{
                FormsAuthentication.RedirectFromLoginPage(username, 
true);
            }

            
else
            
{
                Response.Write(
"<script>alert('Wrong username or password');</script>");
            }
  3.扩展Context.User
  通常情况下,我们可以通过Context.User或者Page.User来获取当前登录用户的信息,这个一个实现了IPrinciple的类,默认类型是GenericPriciple,这个类存储的信息十分有限,下面我们尝试自定义一个IPrinciple.
  比如我想在User中存储QQ号码的相关信息,声明一个类myUser如下:
    public class myUser : IPrincipal
    
{
        
private string _authenticationType;
        
private bool _isAuthenticated;
        
private string _name;
        
private myUser()
        
{ }

        
public myUser(string authenticationType, bool isAuthenticate, string name)
        
{
            _authenticationType 
= authenticationType;
            _isAuthenticated 
= isAuthenticate;
            _name 
= name;
            
switch (_name.ToUpper())
            
{
                
case "JIM":
                    _qq 
= "123456789";
                    
break;
                
default:
                    _qq 
= "987654321";
                    
break;
            }

        }



        
private string _qq;

        
public string QQ
        
{
            
get return _qq; }
            
set { _qq = value; }
        }


        
IPrincipal Members
    }

接着我们要给Context.User赋值,由于ASP.NET是无状态的,所以要在每次请求页面的时候,判断当前用户是否通过验证,如果通过验证,抓取相关信息,赋给Context.User对象.这里需要用到HttpModule, 你可以自己写一个HttpModule,也可以用默认的Global.asax. 在这里我们采用Global.asax.在AuthenticateRequest事件中完成我们的逻辑处理.
        public void Global_AuthenticateRequest(object sender, EventArgs e)
        
{
            HttpApplication app 
= sender as HttpApplication;
            
if (app.Context.User != null)
            
{
                
if (app.Context.User.Identity.IsAuthenticated)
                
{
                    app.Context.User 
= new myUser(app.Context.User.Identity.AuthenticationType, app.Context.User.Identity.IsAuthenticated, app.Context.User.Identity.Name);
                }

            }

        }
这样在页面中就可以取登录用户的QQ号码了.
string qqCode=((myUser)Page.User).QQ;