Spiga

分类为项目实战的文章

数据库调优

2019-11-16 15:35:24

摘要:影响性能因素 * 数据库结构设计 * T-SQL语句 * 数据量大 * 事务和隔离级别 * 硬件资源 * IO阻塞 * 批量删除表数据:大量删除时会记录到日志中,也会造成IO阻塞 阅读全文

鉴权功能实现

2018-11-16 16:46:20

摘要:需求背景 假设,你正在参与开发一个微服务。微服务通过 HTTP 协议暴露接口给其他系统调用,说直白点就是,其他系统通过 URL 来调用微服务的接口。有一天,你的 leader 找到你说,“为了保证接口调用的安全性,我们希望设计实现一个接口调用鉴权功能,只有经过认证之后的系统才能调用我们的接口,没有认证过的系统调用我们的接口会被拒绝。我希望由你来负责这个任务的开发,争取尽快上线。” 需求分析 1. 第一轮基础分析 对于如何做鉴权这样一个问题,最简单的解决方案就是,通过用户名加密码来做认证。我们给每个允许访问我们服务的调用方,派发一个应用名(或者叫应用 ID、AppID)和一个对应的密码(或者叫秘钥)。调用方每次进行接口请求的时候,都携带自己的 AppID 和密码。微服务在接收到接口调用请求之后,会解析出 AppID 和密码,跟存储在微服务端的 AppID 和密码进行比对。如果一致,说明认证成功,则允许接口调用请求;否则,就拒绝接口调用请求。 2. 第二轮分析优化 不过,这样的验证方式,每次都要明文传输密码。密码很容易被截获,是不安全的。那如果我们借助加密算法(比如 SHA),对密码进行加密之后,再传递到微服务端验证,是不是就可以了呢?实际上,这样也是不安全的,因为加密之后的密码及 AppID,照样可以被未认证系统(或者说黑客)截获,未认证系统可以携带这个加密之后的密码以及对应的 AppID,伪装成已认证系统来访问我们的接口。 这就是典型的“重放攻击” 。 提出问题,然后再解决问题,是一个非常好的迭代优化方法。对于这个问题,我们可以借助 OAuth 的验证思路来解决。调用方将请求接口的 URL 跟 AppID、密码拼接在一起,然后进行加密,生成一个 token。调用方在进行接口请求的的时候,将这个 token 及 AppID,随 URL 一块传递给微服务端。微服务端接收到这些数据之后,根据 AppID 从数据库中取出对应的密码,并通过同样的 token 生成算法,生成另外一个 token。用这个新生成的 token 跟调用方传递过来的 token 对比。如果一致,则允许接口调用请求;否则,就拒绝接口调用请求。 3. 第三轮分析优化 不过,这样的设计仍然存在重放攻击的风险,还是不够安全。每个 URL 拼接上 AppID、密码生成的 token 都是固定的。未认证系统截…… 阅读全文

自定义特性+AOP实现缓存

2018-08-21 22:37:30

摘要:1. 目标 如下代码:我们要实现缓存,但希望让使用者不用关心缓存的具体实现,只需要使用者在要操作缓存的方法上加上特性标注即可。 [Caching(CachingMethod.Remove, GetLinksQuery)] public class CreateLinkCommand {     } ​ [Caching(CachingMethod.Get)] public class GetLinksQuery : IRequestListLinkViewModel {     } 要实现我们的目标,我们把任务分成2部分,首先实现缓存逻辑,然后将缓存基于特性做AOP实现。 2. 缓存实现 首先我们定义一个缓存接口 public interface ICacheProvider {    /// summary    /// 向缓存中添加一个对象。    /// /summary    /// param name=key缓存的键值,该值通常是使用缓存机制的方法的名称。/param    /// param name=valKey缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。/param    /// param name=value需要缓存的对象。/param    void Add(string key, string valKey, object value);    void Put(string key, string valKey, object value);    object Get(string key, string valKey);    void Remove(string key);    bool Exists(string key);    bool Exists(string key, string valKey); } 如上代码,为什么接口中key和valKey2个参数呢?这是因为我们可能会缓存同一个方法不同参数的结果,如在一个获取分页结果的方法中,我们可能会返回不同页的结果。如我们目标中GetLinksQuery方法缓存的值会是一个分页显示结果的字典。key是我们缓存的方法名,valKey这是缓存的字典结果中的字典key,value则是字典的结果。要进一步理解可以查看下面基于内存的…… 阅读全文

自制原生js工具库——CSS篇

2008-05-08 12:28:02

摘要:源码 /* ******************************************************************* */ /*   CSS FUNCTIONS                                                     */ /* ******************************************************************* */ var CSS = (function() {    var css = {}; ​    // 转换的RGB字符串的形式“的RGB ( 255 , 255 , 255 ) ”到“ #ffffff ”    css.rgb2hex = function(rgbString) {        if (typeof (rgbString) != string || !defined(rgbString.match)) { return null; }        var result = rgbString.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/);        if (result == null) { return rgbString; }        var rgb = +result[1] 16 | +result[2] 8 | +result[3];        var hex = ;        var digits = 0123456789abcdef;        while (rgb != 0) {            hex = digits.charAt(rgb 0xf) + hex;            rgb = 4;       }        while (hex.length 6) { hex = '0' + hex; }        return # + hex;   }; ​    // 转换字符样式    css.hyphen2camel = function(property) {        if (!defined(property) |…… 阅读全文

自制原生js工具库——Event篇

2008-05-07 21:28:34

摘要:源码 /* ******************************************************************* */ /*   EVENT FUNCTIONS                                                   */ /* ******************************************************************* */ ​ var Event = (function() {    var ev = {}; ​    //阻止事件冒泡    ev.stopBubble = function(e) {        // 如果传入了事件对象,那么就是非IE浏览器        if (e)        // 因此它支持W3C的stopPropagation            e.stopPropagation();        else        // 否则,我们得使用IE的方式取消事件冒泡            window.event.cancelBubble = true;   }; ​    //防止发生默认浏览器行为    ev.stopDefault = function(e) {        // 防止默认浏览器行为(W3C)        if (e) e.preventDefault(); ​        // IE中防止浏览器行为的捷径        return false;   };    //    // 由 Dean Edwards 所编写的addEvent/removeEvent 2005    // 由Tino Zijdel整理    // http://dean.edwards.name/weblog/2005/10/add-event/ ​    ev.addEvent = function(element, type, handler) {        //为每个事件处理函数赋予一个独立的ID        if (!handler.$$guid) handler.$$guid = ev.addEvent.guid++;     …… 阅读全文

自制原生js工具库——DOM篇

2008-05-06 23:33:23

摘要:源码 /* ******************************************************************* */ /*   DOM FUNCTIONS                                                     */ /* ******************************************************************* */ var DOM = (function() {    var dom = {}; ​    //查找相关元素的前兄弟元素    dom.prev = function(elem) {        do {            elem = elem.previousSibling;       } while (elem elem.nodeType != 1);        return elem;   }; ​    //查找相关元素的后兄弟元素    dom.next = function(elem) {        do {            elem = elem.nextSibling;       } while (elem elem.nodeType != 1);        return elem;   }; ​    //查找第一个子元素    dom.first = function(elem) {        elem = elem.firstChild;        return elem elem.nodeType != 1 ? nextSibling(elem) : elem;   }; ​    //查找最后一个子元素    dom.last = function(elem) {        elem = elem.lastChild;        return elem elem.nodeType != 1 ? prevSibling(elem) : elem;   }; ​    //查找父元素    dom.parent = function(elem, num) {        num…… 阅读全文

自制原生js工具库——基础篇

2008-05-05 23:33:45

摘要:源码 /** * Copyright (c)2008 xiaosuo */ /* ******************************************************************* */ /*   UTIL FUNCTIONS                                                   */ /* ******************************************************************* */ var Util = { 'VERSION':1.1 }; ​ //获取id function id(name) {    return document.getElementById(name); } ​ //获取指定元素 function tag(name, elem) {    // 如果不提供上下文元素,则遍历整个文档    return (elem || document).getElementsByTagName(name); } ​ //判断对象是否存在 function defined(o) {    return (typeof (o) != undefined); } ​ /* ******************************************************************* */ /*   OBJECT FUNCTIONS                                                 */ /* ******************************************************************* */ var Obj = (function() {    var object = {}; ​    //检查是否是对象    object.isObject = function(o) {        return (o != null typeof (o) == object defined(o.constructor) o.constructor == Object !defined(o.node…… 阅读全文