.net 常用认证方法 forgery token 认证

来源:互联网 发布:软件开发费用报价 编辑:程序博客网 时间:2024/06/05 12:43

常用的在 asp .net 与 MVC .net中常用的就是 from 认证 与 Windows认证。

对于form认证, 我们需要在web.config下面 system.web节点 加入认证配置。

    <authentication mode="Forms">      <forms loginUrl="~/Account/Login" name=".Acc" protection="All" timeout="30" cookieless="UseCookies" slidingExpiration="true" ticketCompatibilityMode="Framework40" />    </authentication>                <httpCookies httpOnlyCookies="true" />    <sessionState timeout="30" cookieName=".Acc_SessionId" />

在需要认证的方法 或者 class上面,使用 Authorize 属性方法,不需要认证可以用AllowAnonymous 属性,不需要认证。默认情况 不加也是匿名认证。登录成功后,我们会设置form认证的用户名,完成授权。

FormsAuthentication.SetAuthCookie(userName, false);

有时候需要自己重写认证方法,可以在是class 继承实现类中,重写 OnAuthorization 方法,也可以,使用属性类 的方法 来重写。 下面可以判断请求的方式是ajax还是直接通过http 过来的请求。

        protected override void OnAuthorization(AuthorizationContext filterContext)        {            base.OnAuthorization(filterContext);            if (filterContext.Result != null)            {                return;            }            if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(NotRenewSessionAttribute), true).Any())            {                return;            }            if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(NotRenewSessionAttribute), true).Any())            {                return;            }            if (!User.Identity.IsAuthenticated || string.IsNullOrEmpty(ApplicationContext.UserName) || string.IsNullOrEmpty(ApplicationContext.GetSessionId()))            {                if (Request.IsAjaxRequest())                {                    filterContext.HttpContext.Response.StatusCode = 200;                    var ajaxResultModel = new AjaxResultModel();                    ajaxResultModel.Message = Messages.Admin.SessionTimeoutOrKilled.Format();                    SessionException exception = new SessionException(Errors.ErrorCodes.E0501, SessionStatus.Inactive, ajaxResultModel.Message);                    ExceptionInfo exceptionInfo = new ExceptionInfo(exception);                    //ajaxResultModel.ExceptionInfo = exceptionInfo;                    ajaxResultModel.Code = AjaxStatusCode.SessionTimeout;                    ajaxResultModel.IsSuccess = false;                    ajaxResultModel.MessageInfo = ajaxResultModel.Message;                    filterContext.Result = Json(new { data = ajaxResultModel }, JsonRequestBehavior.AllowGet);//new JsonResult { Data = ajaxResultModel, JsonRequestBehavior = JsonRequestBehavior.AllowGet };                }                else                {                    filterContext.Result = new HttpUnauthorizedResult();                }            }        }        protected override void OnActionExecuting(ActionExecutingContext filterContext)        {            if (filterContext.Result != null)            {                return;            }            if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(NotRenewSessionAttribute), true).Any())            {                return;            }            if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(NotRenewSessionAttribute), true).Any())            {                return;            }            string sessionId = this.ApplicationContext.GetSessionId();            if (!string.IsNullOrEmpty(sessionId))            {                try                {                    SessionManager.Renew(sessionId);                }                catch (SessionException)                {                    this.ApplicationContext.SetSessionId(null);                    throw;                }            }            else            {                throw new SessionException(Errors.ErrorCodes.E0503);            }            base.OnActionExecuting(filterContext);        }        protected override void HandleUnknownAction(string actionName)        {            if (this.GetType() != typeof(AcceleratorBaseController))            {                //handle unknow controller                Response.RedirectToRoute(new { controller = "Home", action = "PageNotFound" });            }        }
这里分享下,session 共享问题,前段时间发现,两个站点都在同一台server的iis服务器上面,当登录一个站点时候,另一个如果使用默认form认证的时候,另一个站点也是被授权了,这就是因为他们的session是共享的导致,最后原因发现因为在web配置文件中,两个站点配置了同一样的machineKey导致的,system.web节点。

      <machineKey decryption="AES" decryptionKey="CFE8BCC5155F55D55FAECDB2E5E75867EEAE527D917949A5465248105C2867A1" validation="SHA1" validationKey="9C594C1C1A1C796A7C72C1D4D2568C9E8618BDFF8EBB92C8091CE68B02D5EE7307D1FFB4FDBA174E87C7F3878CC3260EBB7ED713BCB6ADE628E6E89578731E4DC1" />

可以在iis的站点目录下找到machine key配置,然后重新生成key。即可解决问题。这样两个站点就不会同用一个session了。



对于windows 认证,只要在web config下面开启 windows认证即可,你可以直接制定用户,登录时候会弹出默认的windows认证的验证,需要认证。

推荐测试工具,https://insomnia.rest/download/  

 <system.web>    <authentication mode="Windows" />    <!--<authentication mode="Windows">      <forms >        <credentials passwordFormat="Clear">          <user name="administrator" password="password1"></user>        </credentials>      </forms>    </authentication>-->
    <!--<authorization>      <allow users="domain\Administrator"/>      <deny users="?"/>    </authorization>-->

如果是ajax 或者http过来的请求,httpWebRequest.Credentials 把用户名和password传过去即可。

 public static string PostSecurityRequest(string remoteUrl, string postData, string userName, string password, string domain, int timeOut = 60000, string encode = "UTF-8", string contentType = "application/x-www-form-urlencoded")        {            string str = "";            System.Net.HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(remoteUrl);            byte[] bytes = Encoding.GetEncoding(encode).GetBytes(postData);            httpWebRequest.Method = "Post";            httpWebRequest.ContentType = contentType;            httpWebRequest.ContentLength = (long)bytes.Length;            httpWebRequest.Timeout = timeOut;            httpWebRequest.UseDefaultCredentials = false;            httpWebRequest.PreAuthenticate = false;            httpWebRequest.Credentials = new NetworkCredential(userName, password, domain);            Stream requestStream = httpWebRequest.GetRequestStream();            requestStream.Write(bytes, 0, bytes.Length);            requestStream.Close();            Stream responseStream = httpWebRequest.GetResponse().GetResponseStream();            if (responseStream != null)            {                StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encode));                str = streamReader.ReadToEnd();                streamReader.Close();                responseStream.Close();            }            return str;        }


对于防止CSRF跨站请求伪造攻击,我可以可以使用.net的自带【ValidateAntiForgeryToken】 进行验证,只需要加在增删改的方法上面,在from标签里面加入token post到后台即可@Html.AntiForgeryToken()。

对于ajax请求 可以直接获取token post到后台。

var forgeryToken = $("input[name=__RequestVerificationToken]").val(); 

data: { formId: formId, __RequestVerificationToken: forgeryToken  },


中间项目使用angular js 前端, 研究了一下如何使用该功能,我们可以自定义验证方法,把token 在header中传过去。 在master 全局页面中加入token在页面。使用ajax和anjular 封装好的http请求。

        @functions{           public string GetAntiForgeryToken()           {               string cookieToken, formToken;               AntiForgery.GetTokens(null, out cookieToken, out formToken);               return cookieToken + ":" + formToken;           }        }
    <input id="antiForgeryToken" type="hidden" value="@GetAntiForgeryToken()" />  
accept: () => {                $.ajax({                    url: './Request',                    headers: {'RequestVerificationToken': $("#antiForgeryToken")[0].value},                    data: formData,                    type: 'POST',                    contentType: false,                    processData: false,                    dataType: 'json',                    async: false,                    cache: false                }).always(function (jqXHR: any, textStatus: any, errorThrown: any) {                    var data = (jqXHR.responseJSON || jqXHR).data;                    if (data.IsSuccess) {                        messageFlag = "success";                    } else {                        messageFlag = "failure";                        errorMessage = data.MessageInfo;                    }                                  });
导入jquery, declare var $: any;
    options: RequestOptions;    constructor(private http: Http) {        let headers = new Headers();        headers.append('X-Requested-With', 'XMLHttpRequest');        if ($("#antiForgeryToken")) {            headers.append('RequestVerificationToken', $("#antiForgeryToken")[0].value);        }        this.options = new RequestOptions({ headers: headers });    }

在头文件里加入 ajax 请求,和token值。在方法上使用自定义方法验证。

[MyValidateAntiForgeryToken]

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]    public class MyValidateAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter    {        private void ValidateRequestHeader(HttpRequestBase request)        {            string cookieToken = String.Empty;            string formToken = String.Empty;            string tokenValue = request.Headers["RequestVerificationToken"] ?? "";            if (!String.IsNullOrEmpty(tokenValue))            {                string[] tokens = tokenValue.Split(':');                if (tokens.Length == 2)                {                    cookieToken = tokens[0].Trim();                    formToken = tokens[1].Trim();                }            }            AntiForgery.Validate(cookieToken, formToken);        }        public void OnAuthorization(AuthorizationContext filterContext)        {            try            {                if (filterContext.HttpContext.Request.IsAjaxRequest())                {                    ValidateRequestHeader(filterContext.HttpContext.Request);                }                else                {                    AntiForgery.Validate();                }            }            catch (HttpAntiForgeryException e)            {                throw new HttpAntiForgeryException("Anti forgery token cookie not found");            }        }    }



原创粉丝点击