• WebApi Basic基础身份认证


    一:为什么需要身份认证

    没有身份认证,匿名用户只要知道了我们服务的url,就能随意访问接口

    增加了身份认证后,只有拿到票据的请求才能访问接口

    下面是代码示例

    WEB前端

    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    
    </head>
    <body style="">
        <canvas class="pg-canvas" width="1536" height="310"></canvas>
        <div class="login">
            <div class="login_title">
                <span>管理员登录</span>
            </div>
            <div class="login_fields">
                <div class="login_fields__user">
                    <div class="icon">
                        <img alt="" src="/Admin/img/user_icon_copy.png">
                    </div>
                    <input name="login" placeholder="用户名" maxlength="16" type="text" autocomplete="off" value="admin">
                    <div class="validation">
                        <img alt="" src="/Admin/img/tick.png">
                    </div>
                </div>
                <div class="login_fields__password">
                    <div class="icon">
                        <img alt="" src="/Admin/img/lock_icon_copy.png">
                    </div>
                    <input name="pwd" placeholder="密码" maxlength="16" type="text" autocomplete="off">
                    <div class="validation">
                        <img alt="" src="/Admin/img/tick.png">
                    </div>
                </div>
                <div class="login_fields__password">
                    <div class="icon">
                        <img alt="" src="/Admin/img/key.png">
                    </div>
                    <input name="code" placeholder="验证码" maxlength="4" type="text" autocomplete="off">
                    <div class="validation" style="opacity: 1; right: -5px; top: -3px;">
                        <canvas class="J_codeimg" id="myCanvas" onclick="Code();">对不起,您的浏览器不支持canvas,请下载最新版浏览器!</canvas>
                    </div>
                </div>
                <div class="login_fields__submit">
                    <input type="button" value="登录">
                </div>
            </div>
            <div class="success">
            
            </div>
            <div class="disclaimer">
                <p>欢迎登陆后台管理系统 </p>
                <%--<p style="text-align:right;"><a href="Register.aspx" style="color:white;">注册</a></p>--%>
            </div>
        </div>
        <div class="authent">
            <div class="loader" style="height: 44px;  44px; margin-left: 28px;">
                <div class="loader-inner ball-clip-rotate-multiple">
                    <div></div>
                    <div></div>
                    <div></div>
                </div>
            </div>
            <p>认证中...</p>
        </div>
        <div class="OverWindows"></div>
    
        <script type="text/javascript">
            var canGetCookie = 0; //是否支持存储Cookie 0 不支持 1 支持
            var ajaxmockjax = 1; //是否启用虚拟Ajax的请求响 0 不启用  1 启用
            //默认账号密码
    
            var truelogin = "admin";
            var truepwd = "123456";
    
            var CodeVal = 0;
            Code();
            function Code() {
                if (canGetCookie == 1) {
                    createCode("AdminCode");
                    var AdminCode = getCookieValue("AdminCode");
                    showCheck(AdminCode);
                } else {
                    showCheck(createCode(""));
                }
            }
            function showCheck(a) {
                CodeVal = a;
                var c = document.getElementById("myCanvas");
                var ctx = c.getContext("2d");
                ctx.clearRect(0, 0, 1000, 1000);
                ctx.font = "80px 'Hiragino Sans GB'";
                ctx.fillStyle = "#E8DFE8";
                ctx.fillText(a, 0, 100);
            }
            $(document).keypress(function (e) {
                // 回车键事件  
                if (e.which == 13) {
                    $('input[type="button"]').click();
                }
            });
            //粒子背景特效
            $('body').particleground({
                dotColor: '#E8DFE8',
                lineColor: '#133b88'
            });
            $('input[name="pwd"]').focus(function () {
                $(this).attr('type', 'password');
            });
            $('input[type="text"]').focus(function () {
                $(this).prev().animate({ 'opacity': '1' }, 200);
            });
            $('input[type="text"],input[type="password"]').blur(function () {
                $(this).prev().animate({ 'opacity': '.5' }, 200);
            });
            $('input[name="login"],input[name="pwd"]').keyup(function () {
                var Len = $(this).val().length;
                if (!$(this).val() == '' && Len >= 5) {
                    $(this).next().animate({
                        'opacity': '1',
                        'right': '30'
                    }, 200);
                } else {
                    $(this).next().animate({
                        'opacity': '0',
                        'right': '20'
                    }, 200);
                }
            });
            var open = 0;
            layui.use('layer', function () {
                //var msgalert = '默认账号:' + truelogin + '<br/> 默认密码:' + truepwd;
                //var index = layer.alert(msgalert, { icon: 6, time: 4000, offset: 't', closeBtn: 0, title: '友情提示', btn: [], anim: 2, shade: 0 });
                //layer.style(index, {
                //    color: '#777'
                //});
                //非空验证
                $('input[type="button"]').click(function () {
                    var login = $('input[name="login"]').val();
                    var pwd = $('input[name="pwd"]').val();
                    var code = $('input[name="code"]').val();
                    if (login == '') {
                        ErroAlert('请输入您的账号');
                    } else if (pwd == '') {
                        ErroAlert('请输入密码');
                    } else if (code == '' || code.length != 4) {
                        ErroAlert('输入验证码');
                    } else {
                        //认证中..
                        fullscreen();
                        $('.login').addClass('test'); //倾斜特效
                        setTimeout(function () {
                            $('.login').addClass('testtwo'); //平移特效
                        }, 300);
                        setTimeout(function () {
                            $('.authent').show().animate({ right: -320 }, {
                                easing: 'easeOutQuint',
                                duration: 600,
                                queue: false
                            });
                            $('.authent').animate({ opacity: 1 }, {
                                duration: 200,
                                queue: false
                            }).addClass('visible');
                        }, 500);
    
                        //登陆
                        var JsonData = { login: login, pwd: pwd, code: code };
                        //此处做为ajax内部判断
                        var url = "";
                        if (JsonData.code.toUpperCase() == CodeVal.toUpperCase()) {
                            url = "/Tools/Login.ashx";
                        } else {
                            url = "Ajax/LoginFalse";
                        }
    
    
                        AjaxPost(url, JsonData,
                            function () {
                                //ajax加载中
                            },
                            function (data) {
                                console.log(data);
                                //ajax返回 
                                //认证完成
                                setTimeout(function () {
                                    $('.authent').show().animate({ right: 90 }, {
                                        easing: 'easeOutQuint',
                                        duration: 600,
                                        queue: false
                                    });
                                    $('.authent').animate({ opacity: 0 }, {
                                        duration: 200,
                                        queue: false
                                    }).addClass('visible');
                                    $('.login').removeClass('testtwo'); //平移特效
                                }, 2000);
                                setTimeout(function () {
                                    $('.authent').hide();
                                    $('.login').removeClass('test');
                                    if (data.Status == 'ok') {
                                        //登录成功
                                        $('.login div').fadeOut(100);
                                        $('.success').fadeIn(1000);
                                        $('.success').html(data.Text);
                                        //跳转操作
                                        
                                        location.href = "Admin_index.aspx"
                                    } else {
                                        AjaxErro(data);
                                    }
                                }, 2400);
                            })
                    }
                })
            })
            var fullscreen = function () {
                elem = document.body;
                if (elem.webkitRequestFullScreen) {
                    elem.webkitRequestFullScreen();
                } else if (elem.mozRequestFullScreen) {
                    elem.mozRequestFullScreen();
                } else if (elem.requestFullScreen) {
                    elem.requestFullscreen();
                } else {
                    //浏览器不支持全屏API或已被禁用  
                }
            }
            if (ajaxmockjax == 1) {
                $.mockjax({
                    url: 'Ajax/Login',
                    status: 200,
                    responseTime: 50,
                    responseText: { "Status": "ok", "Text": "登陆成功<br /><br />欢迎回来" }
                });
                $.mockjax({
                    url: 'Ajax/LoginFalse',
                    status: 200,
                    responseTime: 50,
                    responseText: { "Status": "Erro", "Erro": "账号名或密码或验证码有误" }
                });
            }
        </script>
    
    
        <div class="layui-layer-move"></div>
    </body>
    </html>
    

      登录API接口

    namespace SW163WebClient.Controllers
    {
        /// <summary>
        /// ==========2022-6-1(小金)===============
        /// </summary>
        public class UserController : ApiController
        {
            /// <summary>
            /// 用户登录
            /// </summary>
            /// <param name="strUser"></param>
            /// <param name="strPwd"></param>
            /// <returns></returns>
            [HttpGet]
            public object Login(string strUser, string strPwd)
            {
                if (!ValidateUser(strUser, strPwd))
                {
                    return new { bRes = false };
                }
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, strUser, DateTime.Now,
                                DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", strUser, strPwd),
                                FormsAuthentication.FormsCookiePath);
    
                //返回登录结果、用户信息、用户验证票据信息
                var oUser = new UserInfo { bRes = true, UserName = strUser, Password = strPwd, Ticket = FormsAuthentication.Encrypt(ticket) };
                //将身份信息保存在session中,验证当前请求是否是有效请求
                //HttpContext.Current.Session[strUser] = oUser;
                return oUser;
            }
    
            public void ProcessRequest(HttpContext context)
            {
                throw new NotImplementedException();
            }
    
            //校验用户名密码
            private bool ValidateUser(string strUser, string strPwd)
            {
                SW163BLL.Administrators blladmin = new SW163BLL.Administrators();
                DataTable dt = blladmin.GetList("UserName='" + strUser + "' and PassWord='" + SW163Common.DESEncrypt.Encrypt(strPwd) + "'").Tables[0];
                if (dt.Rows.Count > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    
        public class UserInfo
        {
            public bool bRes { get; set; }
    
            public string UserName { get; set; }
    
            public string Password { get; set; }
    
            public string Ticket { get; set; }
        }
    }
    

     Home/Index.aspx界面

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace SW163WebClient.Admin
    {
        /// <summary>
        /// 2022-6-1 小金
        /// </summary>
        public partial class Index: System.Web.UI.Page
        {
            public SW163UI.BasePage bg = new SW163UI.BasePage();
            public string UserName = string.Empty;
            public string Ticket = string.Empty;
            public int first = 1;
            protected void Page_Load(object sender, EventArgs e)
            {
                HttpCookie myCookie = HttpContext.Current.Request.Cookies["Web"];
                if (bg.CookieYESNo()) { Response.Redirect("Login.aspx"); }
                else
                {
                    if (myCookie["UserName"] != null && myCookie["Ticket"] != null && myCookie["date"] != null)
                    {
                        UserName = myCookie["UserName"];
                        Ticket = myCookie["Ticket"];
                        //第一次登录时间和当前时间对比,大于30分钟清除cookie;
                        DateTime time = Convert.ToDateTime(myCookie["date"]);
                        DateTime time1 = DateTime.Now;
                        TimeSpan timeSpan = time1 - time;
                        if (timeSpan.TotalMinutes >= 30)
                        {
                            UserName = "";
                            Ticket = "";
                            bg.ExitCookie();
    
                        }
                        else
                        {
                            //当前时间大于第一次登录时间1分钟,非第一次登录
                            if (Convert.ToDateTime(time1.ToString("yyyy-MM-dd HH:mm")) > Convert.ToDateTime(time.ToString("yyyy-MM-dd HH:mm")))
                            {
                                first = 2;
                                myCookie["Ticket"] = "2";
                            }
    
    
                        }
                    }
                    else
                    {
                        bg.ExitCookie();
                        Response.Redirect("Login.aspx");
                    }
                }
            }
    
            //退出登录
            protected void lbtnExit_Click(object sender, EventArgs e)
            {
                bg.ExitCookie();
            }
        }
    }
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="js/jquery.min.js"></script>
         <script type="text/javascript">
             //打开页面的时候保存票据信息
             var UserName ="<%=UserName %>";
             var Ticket = "<%=Ticket%>";
             var first =<%=first%>;
         </script>
    </head>

     <script>
            $(function () {
                $.ajax({
                    type: "get",
                    url: "/api/Charging/GetAllChargingData",
                    data: {},
                    beforeSend: function (XHR) {
                        //发送ajax请求之前向http的head里面加入验证信息
                        XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket);
                    },
                    success: function (data, status) {
                        if (status == "success") {
                            if (first==1) {
                                layer.alert(UserName + ":欢迎回家!");
                            }
                        }
                    },
                    error: function (e) {
    
                         layer.alert("认证信息已过期!请重新登录", function () {
                            //清除kooie
                             $.ajax({
                                 type: "post",
                                 url: "/Tools/Login.ashx",
                                 data: { "act":"clean_up"},
                                 success: function (result)
                                 {
                                     window.location.href = "Login.aspx";
                                 }
                             })
                           
                        });
                    },
                    complete: function () {
    
                    }
    
                });
            });
    
        </script>

    WebAPI项目里面自定义一个类RequestAuthorizeAttribute,去继承AuthorizeAttribute这个类。然后重写OnAuthorization方法,在这个方法里面取到请求头的Ticket信息,再效验用户名和密码是否正确

    /// <summary>
        /// ==========2022-6-1(小金)===============
        /// 自定义此特性用于接口的身份验证
        /// </summary>
        public class RequestAuthorizeAttribute : AuthorizeAttribute
        {
            //重写基类的验证方式,加入我们自定义的Ticket验证
            public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
            {
                //从http请求的头里面获取身份验证信息,验证是否是请求发起方的ticket
                var authorization = actionContext.Request.Headers.Authorization;
                if ((authorization != null) && (authorization.Parameter != null))
                {
                    //解密用户ticket,并校验用户名密码是否匹配
                    var encryptTicket = authorization.Parameter;
                    if (ValidateTicket(encryptTicket))
                    {
                        base.IsAuthorized(actionContext);
                    }
                    else
                    {
                        HandleUnauthorizedRequest(actionContext);
                    }
                }
                //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401
                else
                {
                    var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
                    bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);
                    if (isAnonymous) base.OnAuthorization(actionContext);
                    else HandleUnauthorizedRequest(actionContext);
                }
            }
    
            //校验用户名密码
            private bool ValidateTicket(string encryptTicket)
            {
                //解密Ticket
                var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;
    
                //从Ticket里面获取用户名和密码
                var index = strTicket.IndexOf("&");
                string strUser = strTicket.Substring(0, index);
                string strPwd = strTicket.Substring(index + 1);
    
                SW163BLL.Administrators blladmin = new SW163BLL.Administrators();
                DataTable dt = blladmin.GetList("UserName='" + strUser + "' and PassWord='" + SW163Common.DESEncrypt.Encrypt(strPwd) + "'").Tables[0];
                if (dt.Rows.Count > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    

    在具体的Api接口增加我们上面定义的自定义特性

    /// <summary>
        /// ==========2022-6-1(小金)===============
        /// </summary>
        public class ChargingController : BaseApiController
        {
            /// <summary>
            /// 得到所有数据
            /// </summary>
            /// <returns>返回数据</returns>
            [HttpGet,Route("api/Charging/GetAllChargingData")]
            public string GetAllChargingData()
            {
                return "Success";
            }
    
            /// <summary>
            /// 得到当前Id的所有数据
            /// </summary>
            /// <param name="id">参数Id</param>
            /// <returns>返回数据</returns>
            [HttpGet, Route("api/Charging/GetAllChargingData")]
            public string GetAllChargingData(string id)
            {
                return "ChargingData" + id;
            }
        }
    

    在API添加身份认证公共父类,子类只需继承父类认证即可

    /// <summary>
        /// API 身份认证公共父类
        /// 
        /// ==========2022-6-1(小金)===============
        /// 
        /// origins配置允许访问的域名,多个域名以逗号分隔即可,域名一定要完整,
        /// 如果是ip地址前面要加上“http”,只使用IP的话一定会失效的。
        /// 参数headers配置所支持的资源。
        /// 参数methods配置支持的方法,get、post、put等。
        /// 如果允许任意域名、任意资源、任意方法访问自己的webapi,则三个参数全部使用星号”*”即可
        /// </summary>
        [RequestAuthorize]
        [EnableCors(origins: "*", headers: "*", methods: "*")]
        public class BaseApiController : ApiController
        {
        }
    

    本文转自:https://www.cnblogs.com/landeanfen/p/5287064.html

  • 相关阅读:
    设计模式之策略模式
    assert断言——调试中不应该是syso
    Spring AOP
    MyBatis
    事务处理与使用连接池管理连接
    管理结果集(ResultSet)
    执行SQL语句的方式
    JDBC基础:
    NIO.2
    NIO
  • 原文地址:https://www.cnblogs.com/jstblog/p/16362317.html
Copyright © 2020-2023  润新知