zoukankan      html  css  js  c++  java
  • ASP.NET Web API 实现客户端Basic(基本)认证 之简单实现

    优点是逻辑简单明了、设置简单。

    缺点显而易见,即使是BASE64后也是可见的明文,很容易被破解、非法利用,使用HTTPS是一个解决方案。

    还有就是HTTP是无状态的,同一客户端每次都需要验证。

    实现:

    客户端在用户输入用户名及密码后,将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中,如当用户名为Parry,密码为123456时,客户端将用户名和密码用":"合并,并将合并后的字符串用BASE64加密,并于每次请求数据时,将密文附加于请求头(Request Header)中。

    HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。 

    自定义属性HTTPBasicAuthorize ,继承AuthorizeAttribute,并实现两个方法:OnAuthorization和HandleUnauthorizedRequest。

       public class HTTPBasicAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
        {
            public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
            {
                if (actionContext.Request.Headers.Authorization != null)
                {
              //对客户端进行BASE64后的字符串再解码
                    string userInfo = Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter));
                    //用户验证逻辑
                    if (string.Equals(userInfo, string.Format("{0}:{1}", "Parry", "123456")))
                    {
                        IsAuthorized(actionContext);
                    }
                    else
                    {
                        HandleUnauthorizedRequest(actionContext);
                    }
                }
                else
                {
                    HandleUnauthorizedRequest(actionContext);
                }
            }
    //或不重写OnAuthorization,对IsAuthorized方法重写
            protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
            {
               
                if (actionContext.Request.Method == HttpMethod.Options)
                    return true;
                if (actionContext.Request.Headers.Authorization != null && actionContext.Request.Headers.Authorization.Parameter != null) { 
                 // System.Web.Security.FormsAuthentication.
                   var userdata= System.Text.Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter));
                   if (userdata.Equals(String.Format("{0}:{1}", "tzy", "123"))) {
                       return true;
                        //base.IsAuthorized(actionContext);
                   }
                }
                return false;
               // return base.IsAuthorized(actionContext);
            }
    
    
    
            protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
            {
                var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
                challengeMessage.Headers.Add("WWW-Authenticate", "Basic");
                throw new System.Web.Http.HttpResponseException(challengeMessage);
            }
        }

    这些代码值得注意的地方及说明

    1.  if (actionContext.Request.Method == HttpMethod.Options)   这个判断是在进行跨域访问时浏览器会发起一个Options请求去试探这个请求,但是他不会带着data参数和一些header参数,所以认证肯定没法通过导致无法继续进行,所以给他直接认证通过。(对非跨域的则没有影响)

    2.对Authorization.Parameter 的解密,这里的解析跟登陆成功之后返回的Token 加密方式相同就行 这里采用的是Basic认证方式(简单的64位字符串)

    3.HandleUnauthorizedRequest方法 这里因为是继承重写的AuthorizeAttribute,在IsAuthorized 返回False的时候会执行这个方法

    这里是返回一个401的错误信息

    4.challengeMessage.Headers.Add("WWW-Authenticate","Basic");   这句代码指示浏览器 认证方式为Basic 然后浏览器自动弹出一个登陆窗口并以basic 的方式 加密后每次通过header 传输到服务器进行认证然后得到授权

    在需要验证的Controller的类加上[HTTPBasicAuthorize]属性,即可对当前控制器下的所有方法实现基本身份认证

     然后我习惯更改一下api的路由  就改了一下routeTemplate 加入/{action}

    public static void Register(HttpConfiguration config)
            {
                // Web API configuration and services
    
                // Web API routes
                config.MapHttpAttributeRoutes();
               // config.Filters.Add(new AuthorizeAttribute());
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            }

    如果以webapi里面有xml 方式返回,更改formatter 如下

    protected void Application_Start()
            {
                GlobalConfiguration.Configure(WebApiConfig.Register);
                GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            }

    https://www.cnblogs.com/leo_wl/p/3553385.html
    Basic Authentication
    具体做法:创建一个filter继承自AuthorizationFilterAttribute,重写OnAuthorization来实现我们的需求。
    原理是:客户端在发送Http请求的时候在Header部分提供一个基于Base64编码的用户名和密码,形式为“username:password”,消息接收者(服务器)进行验证,通过后继续处理请求。
    1.从请求Header中获取校验数据
    2.判断验证信息类型为“basic”并包含base64编码
    3.将base64编码转化为string,并提取用户名和密码
    4.校验提供的验证信息是否与访问的资源信息相同(学生的详细信息只能由他自己访问)
    5.去数据库校验用户名及密码
    6.如果校验通过,则设置Thread的CurrentPrincipal,使本次接下来的请求都是通过校验的。
    7.校验没通过,返回401(Unauthorized)并添加一个WWW-Authenticate响应头

  • 相关阅读:
    表单校验神器
    插入排序
    数组去重的几种常使用的方式
    day44 mysql高级部分内容
    day43 多表查询和pymysql
    day42 字段的增删改查详细操作
    day41 mysql详细操作
    day40 mysql数据类型
    day39 mysql数据库基本操作
    day37 异步回调和协程
  • 原文地址:https://www.cnblogs.com/shy1766IT/p/5525695.html
Copyright © 2011-2022 走看看