架构之路(八)从CurrentUser说起

CurrentUser,也就是当前用户,这是我们系统中大量使用的一个概念。

 

确认当前用户

 

当然,我们利用的是cookie:用户的ID存放在cookie中,服务器端通过cookie中的Id,查找数据库,得到需要的用户信息。

 

那么,这里就有一个安全问题,如何防止cookie的伪造或篡改?我们采用了以下方法:

首先,cookie中除了存放用户Id,还存放了一个加密过后的验证码,其来源如下:

  • 未加密的验证码在用户生成时由系统随机产生,并存储在数据库中,如:287653;
  • 它会被使用MD5加密成我们看不懂的字符串,如:49b5f37dff119cf81fcb2b4e6077e17;

所以,当服务器端使用cookie中的用户Id时,会先检查加密过后的验证码是否有效。捏造的验证码是不会通过审核的。

 

还有一点需要说明的是,我们不考虑一个有效的cookie(连同验证码)被盗窃的情形。因为这就相当于你的电脑被别人使用了一样,我们确实无法判断使用你电脑的是不是你本人。

 

为什么没有使用session

 

可能有同学会想到,每次取cookie再查数据库,是不是会增加数据库负担,为什么不考虑session呢?两个方面的原因:

  • session有定时清理机制。不管时间长短,session总有可能被清理掉的时候,这个时候不能让用户再重新登录啊!多麻烦,是不是?你可以if(session["userInfo"]== null),再通过cookie取数据再装到session里,但何苦呢?
  • session难以同步更新,维护起来非常麻烦。比如当前用户发表一篇文章,积分增加了,你就得既改session又改数据库,这个同步过程是比较容易出问题的。
  • 上面两个问题,NHiernate的cache已经做得很好了,不会增加数据库负担,这个以后会讲。

 

CurrentUser的ViewModel

 

CurrentUser最麻烦的一件事情是:很多页面是根据不同的当前用户,显示不同的内容的。以“任务编辑”页面为例,当前用户是该任务的发布人,发布栏可编辑;否则,发布栏仅仅是可读的。

 

所以,最初我们的方案很简单,也封装一个CurrentUserModel就可以了呀!

但后来我们发现:

  • 需要判断的东西越来越多,比如还要判断当前用户是不是管理员、当前用户有没有验收权限、当前用户的上一次操作……把这些所有的信息都装到一个ViewModel里肯定是不合适的。怎么办呢?想到的自然就是拆分类,但CurrentUser还怎么拆分呢?
  • 页面的判断逻辑也变得复杂起来,比如当前用户有没有某种权限得查他的申请历史和批准情况,并且还得看当前文章是那种类型及其作者的权限等。这些大段大段的逻辑就写在View里面么?关键是有些数据是单个View取不到的,需要从其他地方(比如url parameter中)获取,这些都进一步的增加了复杂性。让我们不得不考虑,我们是不是应该把这些逻辑移到Controller中,然后直接将结果告诉View,保持View的干净清爽?

 

在MVC架构中,Controller将Model传递给View,其实可能有两种情况:

  1. View直接呈现Model的数据,比如直接显示CurrentUser的用户名
  2. View还可以利用Model中的数据进行运算,然后予以呈现,比如比较CurrentUser和当前任务的承接人

我曾经计划禁止掉第2种情形,也就是说:在View里面不需要任何计算,只负责呈现。用代码表示就是:

@if (Model.CurrentUserIsAccepter)
{
  //CurrentUserIsAccepter的值在controller中获取 }

而不是之前的:

@if (Model.CurrentUser.Id == Model.Accepter.Id)
{}

 

但我们最终放弃了,因为实现起来太臃肿了。我们可以想象,这样的话,我们首先就至少需要三个Is属性:

    public class EditModel{public bool IsAccepter { get; set; }public bool IsOwner { get; set; }public bool IsPublisher { get; set; }}

有点怪,但好像还可以接受,但后来情况发生了变化,我们还得考虑当前用户即是发布人又是承接人,或者即是承接人又是验收人,或者既是……又是……的情形:

    public class EditModel{public bool IsAccepter { get; set; }public bool IsOwner { get; set; }public bool IsPublisher { get; set; }public bool IsBothAccepterAndOwner { get; set; }public bool IsBothAccepterAndPublisher { get; set; }public bool IsBothPublisherAndOwner { get; set; }//......
}

这代码给人的感觉就是有病了。关键是,谁知道以后还来不来一个“是…和…但不是……”的逻辑呢?到时候又该怎么办呢?

 

//任务编辑页面(/Task/Edit/{taskId})是一个页面呈现逻辑比较复杂的典型例子,我们前后大改了三次,才形成今天所使用的代码格局。
//我以前说我带的一个妹纸看着代码哭,哭的就是这里,呵呵
//有兴趣的同学可以研究一下。

 

所以,取巧是不行了,我们还是得面对这个问题:

 

如何划分Controller和View之间的逻辑/责任

 

更直白一点的讲,哪些事该Controller做,哪些事该View做?这个问题真的超级虐心。我想来想去,只能说:“能Controller做的,尽量让Controller做”。我自己对这个问题都相当不满意,但实在是没有办法啦。

具体到CurrentUser的ViewModel,我们提出以下两个原则:

  • 不包含需要和其他对象交互运算才能得到的数据,比如当前用户是不是当前任务的发布人,需要和“当前任务的发布人”做比较,就不能包含进来
  • 只能是需要多个View共用的数据,才能放进来。比如用户名,很多View都需要,就放进来好了。

 

为什么需要明确这些原则

 

可能你耐着性子看了上面的分析,最后却只得到一个似是而非又蛋疼的原则,会忍不住的问,“为什么一定需要/讲解这些原则?让程序员根据实际情况,自由发挥,不行么?”

 

浅层次的原因是要保证代码的可读性。阅读别人的代码是一件非常累的事情。但如果所有的代码都像一个人写的,而且这个人的思路自始至终都是非常清晰的,这样,我们会稍稍轻松一点。代码不是文学作品,在绝大多数情况下,不能天马行空自由发挥!

我们很多开发人员都已经开始注意代码的规范,但大多数还停留在缩进、换行、命名之类的细节(当然,这些也很重要)上;而架构师应站在一个更全局的高度,来“规范”所有的开发行为。

 

所以,其实更深层次的原因是:所有的代码都必须规范化。既然要规范化,那么首先就要有规范!先可以不管好坏,但至少要有。那么怎么制定完善这个规范呢?我分享一下我的经验:

  1. 按规范文档,做入职培训,培训可以着重讲道理,强化开发人员代码规范化的思维;
  2. 所有代码都必须review。review要往“挑刺”的方向靠,所以不规范的代码其实是很容易被发现的;
  3. 开发人员不服review的结果,review的人员要拿出依据(规范文档)来;
  4. 规范文档中如果还没有相关的规定,立即补充,并照此执行,包括改正以前不合规范的代码

这样不断的迭代,基本上就能不断的提高代码的规范性,并得到一份不错的规范文档。

 

好像写跑题了,又是项目管理方向的东西。就先这样吧!前台的架构,想想,剩下的应该就是单元测试(都还没做,所以暂时也讲不了),还有可能其他一些细节了,以后查漏补缺吧。接下来希望参与到项目的前台开发的同学就可以开始联系我了。博客系列我们将接着讲Service层。

 

转载于:https://www.cnblogs.com/freeflying/p/5018787.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357930.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手写爬虫框架

前言 参照了Scrapy、Feapder的设计模式,实现的一个轻量级爬虫框架(目前约200行代码) 源码地址 https://gitee.com/markadc/pader 项目持续更新中…

cmseasy漏洞复现

介绍 提供可视化编辑企业网站管理系统系统、网站模板、以及相关文档资料下载,网站系统完美运 行PHP7环境中。 官方网站: https://www.cmseasy.cn/ cmseasy_7.3.8 任意文件操作漏洞复现 cmseasy_7.6.3.2逻辑漏洞复现 "无需代码,自由拖拽布局,适应…

教你如何看待程序员这个职业的前前后后

现在大家的学历基本提升上来啦,基本搞编程的都是本科或者大专起步,这里仅那本科举例。 好多大学生跟我说是计算机专业,软件工程专业等,啥都学一点,这样真的好? 对于大学生,如果是计算机相关专业…

请领导批阅文件怎么说_刚到公司,应该怎么喊领导,别直接说名字,高情商这样称呼...

刚到公司,应该怎么喊领导,别直接说名字,高情商这样称呼我们都有经历过刚刚从大学毕业出来后,寻求工作的场景。一般来说,我们都是会选择和自己大学所学专业挂钩的职业,在这样的情况下, 我们的选择…

正则表达式的汉字匹配

这里是几个主要非英文语系字符范围 2E80~33FFh:中日韩符号区。收容康熙字典部首、中日韩辅助部首、注音符号、日本假名、韩文音符,中日韩的符号、标点、带圈或带括符文数字、月份,以及日本的假名组合、单位、年号、月份、日期、时…

分屏显示_2021元旦高性价比显示器推荐——便携式显示器选购指南(分屏办公、小尺寸办公必备)...

想要告别小显示器选择困难症,挑选到自己心仪的小显示器,大家看这篇文章就够了!显示器是PC的重要组成部分,在应用程序级别具有“场景”属性。显示器的要求因办公,娱乐和学习等不同应用而异。无论应用场景如何&#xff0…

为Jersey 2.19创建共享库以与Weblogic 12.1.3一起使用

Weblogic服务器带有一个共享库,因此您可以部署JAX-RS 2.0应用程序。 但是仅限于Jersey 2.5.1版,更改的说明并不完全清楚或直观 。 我最近加入了Oracle的新团队,我要做的第一件事就是着眼于升级依赖库。 现在我已经与泽西队进行了交谈&#xf…

一键反编译Android包教程

功能介绍 某些时候我们想修改apk包内容,比如汉化某个游戏,这时候就需要修改游戏apk的包内容,并重新签名成安卓手机识别的apk文件,下面详细介绍,文章末尾有一键修改工具。(注意:此工具尚未整合修…

发现一个可视化大屏操作神器FBI,你值得一试

FineBI 是帆软软件有限公司推出的一款商业智能(Business Intelligence)产品。 FineBI 自助分析以业务需求为方向,通过便携的数据处理和管控,提供自由的探索分析。 FineBI 定位于自助大数据分析的 BI 工具,能够帮助企业的业务人员和数据分析师,开展以问题导向的探索式…

贝叶斯决策

参考文献:http://wenku.baidu.com/link?urlbCWUt2SDACsX6CXndtF8uEeYRo9r33hDVTaDORFcd8sAWbL4hYqmjDeyn5RfyYZ3VjzbnQvLVrNoBapp617_kmTCCKlDV4K_1E4-nTenauO 1)Neyman-Pearson 准则 2)最小错误率准则 3)贝叶斯风险最小准则 4&a…

使用java发送电子邮件_使用Java发送电子邮件

使用java发送电子邮件我开始使用Java作为简单的“如何发送电子邮件”来撰写这篇文章,但是后来我发现我需要简要解释更多事情。 因此,这是有关使用Java发送电子邮件的所有摘要。 在Java SE平台之外(但包含在JavaEE中), …

uniapp去掉右侧滚动条的解决办法?

用 uniapp 开发小程序,内容多的情况下,在微信开发者工具和真机调试下,右侧出现滚动条,有没有办法隐藏滚动条? 参考文档:https://uniapp.dcloud.net.cn/collocation/pages?id=app-plus 解决办法一: 参考文档:https://uniapp.dcloud.net.cn/collocation/pages?id=app-plus…

内网渗透工具CobaltStrike使用教程详解

文章目录 前言一、CobaltStrike本次实验环境 二、CobaltStrike详细使用1.启动CobaltStrike2.客户端连接团队服务端3.配置监听器4.生成木马5.权限提升,命令执行以及内网横线穿透等。6.插件加载7.命令执行等操作8.目标信息总结表(自动记忆保存&#xff09…

日志长度_Kafka 日志存储详解

点击上方“Java知音”,选择“置顶公众号”技术文章第一时间送达!作者:爱宝贝丶my.oschina.net/zhangxufeng/blog/3114166本文主要介绍kafka中日志的存储原理,主要内容包括kafka日志存储格式、日志文件的管理方式、日志索引文件的格…

怎样理解阻塞非阻塞与同步异步的区别?

本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2015-07/120338.htm “阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解,提供一个从分布式系统角度的回答。 1.同步与异步同…

【算法图解|1】js 实现一个函数,完成超过范围的两个大整数相加功能

这个问题中的两个数字,都是超出范围的,所以就不能简单的把两个数字,转为Number类型,进行相加。 需要取两个数字的每一位,进行相加,大于10,就进1,把结果保存在一个字符串中。 主要思路…

Apache Spark:更改架构之前必须解决的5个陷阱

迁移到Apache Spark之前需要了解的5件事 似乎每个人都只是在谈论最热门的新技术,而忽略采用它的真正含义。 但这是自然的,对吧? 新功能和承诺胜过其他一切,而艰巨的挑战和决​​定被抛在一边。 这次不行。 软件架构很难&#xf…

git config配置文件

设置 git status的颜色。 git config --global color.status auto 一.Git已经在你的系统中了,你会做一些事情来客户化你的Git环境。你只需要做这些设置一次;即使你升级了,他们也会绑定到你的环境中。你也可以在任何时刻通过运行命令来重新更改…

双清模式无命令_linux性能监控:IO性能监控命令之iotop命令

内存监控命令之iotop命令1概述:iotop命令 是一个用来监视磁盘I/O使用状况的top类工具。iotop具有与top相似的UI,其中包括PID、用户、I/O、进程等相关信息。Linux下的IO统计工具如iostat,nmon等大多数是只能统计到per设备的读写情况&#xff0…

【算法图解|2】JavaScript 如何实现数组扁平化

数组的扁平化,就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组。 举个例子,假设有个名为 flatten 的函数可以做到数组扁平化, var arr [1, [2, [3, 4]]]; console.log(flatten(arr)) // [1, 2, 3, 4] 我们最一开始…