成员,授权,安全性

本文详细介绍了如何在ASP.NET MVC中自定义权限管理,通过重写AuthorizeAttribute类实现灵活的用户认证与授权逻辑,包括自定义权限验证、处理未授权请求以及使用全局过滤器。同时,解释了OAuth与OpenID的区别,以及如何在项目中应用OAuth进行授权。此外,还讨论了安全策略、令牌验证、Forms认证、错误处理和日志记录等关键安全概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MVC 自定义AuthorizeAttribute实现权限管理

在上一节中提到可以使用AuthorizeAttribute进行权限管理:

复制代码
        [Authorize]
        public ActionResult TestAuthorize()
        { 
            return View();
        }

        [Authorize(Users="test1,test2")]
        public ActionResult TestAuthorize()
        { 
            return View();
        }

        [Authorize(Roles="Admin")]
        public ActionResult TestAuthorize()
        { 
            return View();
        }
复制代码
在代码中:
IPrincipal user=httpContenxt.user;
if(!user.Identity.IsAuthenticated)return false;

但是通常情况下,网站的权限并不是固定不变的,当新增角色或者角色改变时,只能修改每个Action对应的特性,当项目较大时工作量可想而知。幸运的是我们可以重写AuthorizeAttribute达到自定义的权限管理。新建一个CustomAuthorizeAttribute类,使这个类继承于AuthorizeAttribute。打开AuthorizeAttribute查看下方法说明,我们只需要重写AuthorizeCore和OnAuthorization就能达到我们的目的。


代码顺序为:OnAuthorization-->AuthorizeCore-->HandleUnauthorizedRequest

 


如果AuthorizeCore返回false时,才会走HandleUnauthorizedRequest 方法,并且Request.StausCode会返回401,401错误又对应了Web.config中

<authentication mode="Forms">
      <forms loginUrl="~/" timeout="2880" />
    </authentication>

所有,AuthorizeCore==false 时,会跳转到 web.config 中定义的  loginUrl="~/"

 

 public class CheckLoginAttribute : AuthorizeAttribute
    {

        protected override bool AuthorizeCore(HttpContextBase httpContext)        {
            bool Pass = false;
            if (!CheckLogin.AdminLoginCheck())
            {
                httpContext.Response.StatusCode = 401;//无权限状态码
                Pass = false;
            }
            else 
            {
                Pass = true;
            }

            return Pass;
        }

      

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {


            if(filterContext.HttpContext.Request.IsAjaxRequest())
            {
                if (!App.AppService.IsLogon)
                {

                    filterContext.Result = new JsonResult
                                               {
                                                   Data = new {IsSuccess = false, Message = "不好意思,登录超时,请重新登录再操作!"},
                                                   JsonRequestBehavior = JsonRequestBehavior.AllowGet
                                               };
                    return;
                }
            }
            if (App.AppService.IsLogon)
            {
                return;
            }

            base.HandleUnauthorizedRequest(filterContext);
            if (filterContext.HttpContext.Response.StatusCode == 401)
            {
                filterContext.Result = new RedirectResult("/");
            }
        }
      

      
    }

 

AuthorizeAttribute的OnAuthorization方法内部调用了AuthorizeCore方法,这个方法是实现验证和授权逻辑的地方,如果这个方法返回true,


   表示授权成功,如果返回false, 表示授权失败, 会给上下文设置一个HttpUnauthorizedResult,这个ActionResult执行的结果是向浏览器返回


   一个401状态码(未授权),但是返回状态码没什么意思,通常是跳转到一个登录页面,可以重写AuthorizeAttribute的

   HandleUnauthorizedRequest 
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            else
            {
                string path = context.HttpContext.Request.Path;
                string strUrl = "/Account/LogOn?returnUrl={0}";
                
                context.HttpContext.Response.Redirect(string.Format(strUrl, HttpUtility.UrlEncode(path)), true);
                
            }
            
        }

 

MVC3 全局验证、过滤

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new System.Web.Mvc.AuthorizeAttribute());
            filters.Add(new HandleErrorAttribute());
        }

[AllowAnonymous]加到控制器方法或类前让匿名用户访问

1、首先定义一个全局类:


using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Web.Mvc;
using  System.Web;
using  System.Web.Script.Serialization;
using  System.Configuration;
using  System.Web.Security;
using  System.Net;
using  System.IO;
using  ModelProject;
using  System.Web.Routing;
using  System.Runtime.Remoting.Contexts;

namespace  UtilityBase
{

    [ AttributeUsage ( AttributeTargets .All, AllowMultiple =  true )]
     ///  <summary>
     ///  <para>  功|    能:o自?定义?全?局?过y滤?器   </para>
     ///  <para>  作    者?:o韩?保新?  </para>
     ///  <para>  创建日?期: 2011-7-25 9:39:13  </para>
     ///  </summary>
     public  class  GloalMvcFiters  :  ActionFilterAttribute
    {
         public  string  Message {  get ;  set ; }
         private  const  string  WebService_Root =  "WebServiceRoot" ;
         ///  <summary>
         ///  控?制?器方?法执行D之?后执行D
         ///  </summary>
         ///  <param name="filterContext"></param> : 
         public  override  void  OnActionExecuted( ActionExecutedContext  filterContext)
        {
             base .OnActionExecuted(filterContext);
             var  fullName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
           
             if  (!System.Web. HttpContext .Current.User.Identity.IsAuthenticated && !GetList().Contains(fullName))
            {
                 //System.Web.HttpContext.Current.Response.Redirect("~/Account/LogOn", true);
                filterContext.Result =  new  RedirectToRouteResult ( "Default" ,  new  RouteValueDictionary ( new  { area =  "" , controller =  "Account" , action =  "LogOn"  }));
            }
        }
         ///  <summary>
         ///  控制器方法执行之前执行
         ///  </summary>
         ///  <param name="filterContext"></param>
         public  override  void  OnActionExecuting( ActionExecutingContext  filterContext)
        {
             //var s = "</br>控制器名称:" + filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName + "</br>操作方?法:o" + filterContext.ActionDescriptor.ActionName;
             //filterContext.HttpContext.Response.Write(@"<br />Before Action Excute" + "\t "+ s +"\t"+ Message);
             //filterContext.HttpContext.Response.End();
             base .OnActionExecuting(filterContext);
        }
         ///  <summary>
         ///  视图加载完成后执行
         ///  </summary>
         ///  <param name="filterContext"></param>
         public  override  void  OnResultExecuted( ResultExecutedContext  filterContext)
        {
             //filterContext.HttpContext.Response.Write(@"<br />After ViewResult Excute" + "\t " + Message);
             base .OnResultExecuted(filterContext);
        }
         ///  <summary>
         ///  视图加载之前执行
         ///  </summary>
         ///  <param name="filterContext"></param>
         public  override  void  OnResultExecuting( ResultExecutingContext  filterContext)
        {
             //filterContext.HttpContext.Response.Write(@"<br />Before ViewResult Excute" + "\t " + Message);
             base .OnResultExecuting(filterContext);
        }
         private  List < string > GetList()
        {
             List < string > list =  new  List < string >();
            list.Add( "WebUI.Controllers.AccountController" );
            list.Add( "WebUI.Controllers.ErrorController" );
             return  list;
        }
    }
}

2、Global.asax中注册

     protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalFilters.Filters.Add(new UtilityBase.GloalMvcFiters() { Message = "Gloable" });
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

OAuth关注的是authorization;而OpenID侧重的是authentication。从表面上看,这两个英文单词很容易混淆,但实际上,它们的含义有本质的区别:

authorization: n. 授权,认可;批准,委任 authentication: n. 证明;鉴定;证实 OAuth关注的是授权,即:“用户能做什么”;而OpenID关注的是证明,即:“用户是谁”。下面就分别来说两者的功能。 OpenID 用户希望访问其在example.com的账户 example.com (在OpenID的黑话里面被称为“Relying Party”) 提示用户输入他/她/它的OpenID 用户给出了他的OpenID,比如说”http://user.myopenid.com” example.com 跳转到了用户的OpenID提供商“mypopenid.com” 用户在”myopenid.com”(OpenID provider)提示的界面上输入用户名密码登录 “myopenid.com” (OpenID provider) 问用户是否要登录到example.com 用户同意后,”myopenid.com” (OpenID provider) 跳转回example.com example.com 允许用户访问其帐号 OAuth 用户在使用example.com时希望从mycontacts.com导入他的联系人 example.com (在OAuth的黑话里面叫“Consumer”)把用户送往mycontacts.com (黑话是“Service Provider”) 用户在mycontacts.com 登录(可能也可能不用了他的OpenID) mycontacts.com问用户是不是希望授权example.com访问他在mycontact.com的联系人 用户确定 mycontacts.com 把用户送回example.com example.com 从mycontacts.com拿到联系人 example.com 告诉用户导入成功 OpenID是用来验证的,就是说可以用一个url来唯一表明身份(不用挨个记每个网站的用户密码)。OAuth是用来授权的(俺可以授权一个网站访问俺在另外一个网站的数据,而俺不用把俺的密码给第一个网站。

        public static void RegisterAuth()         {             OAuthWebSecurity.RegisterFacebookClient(//配置OAuth                 appId: "123456789012",                 appSecret: "sldifemnivniesasx");         }

[RequireHttps]//所有调用都通过Https进行传输,这反过来导致白提供器使用HTTPS回调到我们的网站。Google和HTTPS一起使用是很重要的。Google会通过HTTP报告一个登录用户,而后对于两个不同的用户,会通过HTTPS报告。使用HTTPS就没有这个问题
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
	ViewBag.ReturnUrl=returnUrl;
	return View();
}

安全
默认在JAVASCRIPT中插入的 @ViewBag.UserName 数据是不进行编码的
@Html.Raw()不进行编码
@Encoder.JavaScriptEncode(@ViewBag.UserName,false) 进行编码来插入JavaScript代码中


FormsAuth.SignOut();//登出

令牌验证
在网页中:
@Html.AntiForgeryToken()//插入一个令牌

在控制器方法上调用 [ValidateAntiforgeryToken]来进行验证 是这个页面的回调。

@using (Html.BeginForm( " Text ", " Home ",FormMethod.Post))
{
     @Html.AntiForgeryToken()
    @:网站公告:<input type= " text " name= " Notice " id= " Notice " />
<input type= " submit " value= " Submit " />
}

对应的Action

        [HttpPost]
         [ValidateAntiForgeryToken]
         public ActionResult Text()
        {
            ViewBag.Notice = Request.Form[ " Notice "].ToString();
             return View();
        }

第二种
HttpReferrer来进行验证
...

web.config
<httpCookies domain="" httponlyCookies="true" requireSSL="false"/>/Response.Cookies["MyCookie"].HttpOnly=true  全局和个别 只读

Bind属性用来阻止黑名单内的成员接收数据。如UpdateModel(Enquiry )  如果Latitude 有值,但他不会被提交到Enquiry 对象中。
  1. [Bind(Include="EnquiryId ")]  //白名单
  2. public class Enquiry {  
  3.   
  4.     public int EnquiryId { get; set; }  
  5.     public string Latitude { get; set; }  
  6. }  

  1. [Bind(Exclude="EnquiryId ")]  //黑名单
  2. public class Enquiry {  
  3.   
  4.     public int EnquiryId { get; set; }  
  5.     public string Latitude { get; set; }  
  6. }  


<system.web>
<deployment retail="true"/>
</system.web>
customErrors mode被设置为On
禁用跟踪输出
禁用调试

ELMAH 错误日志记录系统 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值