HTML+LayUI+WebApi 简单个人小白demo制作
二.webapi
一个有梦想的咸鱼做的一个有梦想的demo项目就需要有梦想的考虑后期维护与扩展,那么就需要从建项目开始做好文件分类。
打开vs,选择asp .net web应用程序(.net framework)创建一个新的项目命名demo,然后选择web api,然后建立项目。注意看项目下有个area的文件夹,作用呢其实就是可以区分控制器,方便管理,而且控制器名称可以重名。
毕竟是个b/s项目,后台所接收的请求都属于http请求,要处理这些请求后台,就会涉及到安全问题,也就是权限问题,毕竟要有梦想,还是可以发布上服务器的。而这个安全问题并不是只用用户登录验证就能解决的,这时候就会涉及到权限问题,参考淘宝,你可以随意浏览,但是一些额外操作则需要登录。
所以这里我是考虑formsauthenticationticket身份验证配合授权属性authorizeattribute。
ticket,顾名思义,想入场看比赛是需要门票的,那么想进入自己的网站或者有数据库操作时,我们可以为用户设置门票。
进而小朋友些许问号,演唱会门票还有前排后排区别,考虑到实际应用情况,我们是否也需要对于用户进行权限区分,这样比较符合实际情况?这样是否更灵活?用户与角色都能去控制
controller的权限是否更科学?没错,尤其是mvc项目,但是这里先不考虑这么多,我们后台只提供接口服务。这里我只是提供一个思路,因为要做一个大度的人,只要人进得来,场地*活动好吧。(就是懒~)
所以会需要使用到授权属性authorizeattribute类。
- authorizeattribute
authorizeattribute类是.net framework框架下提供写好的一个类,authorization(授权)属于过滤器的一种。
这里可以提下当引用authorizeattribute类时方法的执行过程。当给某一个 controller 指定一个权限认证特性后,当程序需要调用这个controller时,会先进入namespace为system.web.http的authorizeattribute公共类,而后首先会执行authorizeattribute 中的 onauthorization 方法,在 onauthorization 函数的执行过程中,如果验证失败了,系统会调用 handleunauthorizedrequest方法来进行处理,基于此原理,我们可以重写这两个方法,然后自定义自己的authorizeattribute。而如果想提供匿名访问服务,即调用controller时不进入authorizeattribute,它提供了allowanonymousattribute属性,字面意思也知道。
基于上述的执行过程,既然是虚函数,我们重写他的两个主要方法。
首先,新建文件夹filter,文件夹下新建一个继承于authorizeattribute的类,以xxauthorizeattribute命名,xx则就是自定义的特性名称。我这里是apiauthorizeattribute。
首先重写onauthorization(httpactioncontext actioncontext)。
/// <summary> /// api权限特性 /// </summary> [attributeusage(attributetargets.class|attributetargets.method)] public class apiauthorizeattribute : authorizeattribute { public override void onauthorization(httpactioncontext actioncontext) { var authorization = actioncontext.request.headers.authorization; if (actioncontext.actiondescriptor.getcustomattributes<allowanonymousattribute>(true).count != 0 || actioncontext.actiondescriptor.controllerdescriptor.getcustomattributes<allowanonymousattribute>(true).count != 0) { base.onauthorization(actioncontext);//正确的访问方法 } else { if (authorization != null && authorization.parameter != null) {this.handleunauthorizedrequest(actioncontext);//没有权限 } else { this.handleunauthorizedrequest(actioncontext);//没有权限 } } } protected override void handleunauthorizedrequest(httpactioncontext actioncontext) { base.handleunauthorizedrequest(actioncontext); } }
梳理下逻辑:
首先,通过httpactioncontext 获得我们在ajax中传入的requset.headers.authorization.
然后,通过判断是否有allowanonymousattribute标识。
结合实际场景来理解这一步,还是上文例子。我总不可能一个演唱会主角还没进场就给保安拦着了要我出示票据???我自己唱歌难道还要自己出钱买票欸?好气哦是不是?
是的,如果你是保安你就被喷了,那一样的,如果你是这个项目的开发者,整个项目运行起来就没一个人能登录进来,连你自己都进不去,所以考虑实际开发不要反人类逻辑思考,那么就提供了allowanonymousattribute。通过在控制器上加上[allowanonymous],相当于走绿色通道不要门票,那么这个最应该放在哪呢?
如果没有关系走不了后门,那么就老实判断有无门票。
然后如果没有,保安赶人,也就是进入handleunauthorizedrequest方法,这是会直接将页面重定向到登录页面。当然你要是宅心仁厚是个文化人,不想要保安如此粗鲁,自己重写代码
返回一段现在最流行的json数据问问施主可还有其他诉求。
这里就会涉及到一个问题,webapi的返回值是不支持的json格式的,如果又不想更改配置,那么可以利用httpresponsemessage返回json。
return new httpresponsemessage() { content = new stringcontent("string", encoding.utf8, "application/json"), };
这一步做完,是不是觉得终于可以进行激动人心的登录仪式了?
想什么呢,什么都没有。数据库你都没有呢朋友。建库建表都还没进行呢。
- orm
- entity framework
object relational mapping,对象关系映射。
这个内容很多,这里使用entity framework,毕竟.net一套。至于为什么,最直接的就是因为不想写sql语句而且安全,这理由还不充分吗?不行你往你自己用sql语句写的登录网站试试输入' or 1 = 1 --',看看会不会有惊喜?有惊喜的少年恭喜你真的很适合看我的博客,给个关注给个推荐谢谢嗷。
下个定义:ef是微软基于ado .net而开发的一套跨数据库的orm框架(hhhhhh这里就不做过多赘述了,资料很多,我自己也写了一个word文档,如果全小白自学的可以联系我发给你哈哈哈,其实后面会单独写ef的,还会浅谈下自学的entity framework core,毕竟我也很菜)
在解决方案demo下建立data文件夹,文件夹下新建一个.net frameworek的类库,取名domain,domain类库下建立models文件夹,此文件夹下建立实体类。
建库建表时就要考虑到项目需求问题,这点很重要很重要很重要,这也时有无项目经验的主要体现。加粗加红好了。
因为是个简单教程,那么我这个项目,目前先做个做个能给每个公司提供管理员工,管理自己公司信息报表的简单平台。后期纵向横向发展那些再说。比如加个department表之类的,然后再来个上级管理,下级官吏啊啧啧啧,少年自己冲。
我们先建立简单的三张表,一张员工表,提供账号密码以及简单个人信息问题。一张账号信息表,方便记录一些账号操作行为。一张公司表,提供基础信息。
公司与员工的关系,员工与账号的关系,设置一个公司有一个管理账号,那么又有
建表时,考虑到更新性原因,尽量不适用外键,所有依赖关系通过自己去思考,比如账号信息表是不是应该有个用户id字段,以便于进行联表操作之类,同时对于删除问题,可以根据不同情景,去考虑使用物理删除还是逻辑删除。
这里简单提下物理删除和逻辑删除的区别:物理删除是删除数据库中的数据,不具有恢复性。而逻辑删除,不删除数据库中的数据,而是通过一些自定义的flag去判断,可以理解为黑名单,你可以表格中设置bool 类型字段deletesian,为true时可以使用,为false时拉黑,禁用,当需要时可以解除拉黑。
employeemodel类:
using system.componentmodel.dataannotations; using system.componentmodel.dataannotations.schema; namespace demo.domain.models { [table("employeesinfo")] public class employeesinfomodel { [key] public int employeesid { get; set; } public int companyid { get; set; } /// <summary> /// 员工姓名 /// </summary> public string name { get; set; } /// <summary> /// 性别 /// </summary> public string sex { get; set; } /// <summary> /// 工号 /// </summary> public string jobnumber { get; set; } /// <summary> /// 员工电话 /// </summary> public string mobile { get; set; } /// <summary> /// 账号 /// </summary> public string accountnum { get; set; } /// <summary> /// 密码 /// </summary> public string passwords { get; set; } /// <summary> /// 账号身份 /// </summary> public int accountrole { get; set; } /// <summary> /// 员工职位 /// </summary> public int employeerole { get; set; } public bool deletesign { get; set; } } }
accountinfomodel类:
using system; using system.componentmodel.dataannotations; using system.componentmodel.dataannotations.schema; namespace demo.domain.models { [table("accountinfo")] public class accountinfomodel { [key] public int accountid { get; set; } /// <summary> /// 账号名 /// </summary> public string accountname { get; set; } public int employeesid { get; set; } /// <summary> /// 管理查询 /// </summary> public int companyid { get; set; } /// <summary> /// 登陆次数 /// </summary> public int logincount { get; set; } /// <summary> /// 开号时间 /// </summary> public datetime? createtime { get; set; } public string createip { get; set; } /// <summary> /// 最后登陆时间 /// </summary> public datetime? lastlogintime { get; set; } public string lastloginip { get; set; } } }
companyinfomodel类:
using system; using system.componentmodel.dataannotations; using system.componentmodel.dataannotations.schema; namespace demo.domain.models { [table("companyinfo")] public class companyinfomodel { /// <summary> /// 编号 /// </summary> [key] public int companyid { get; set; } /// <summary> /// 省 /// </summary> public string province { get; set; } /// <summary> /// 市 /// </summary> public string city { get; set; } /// <summary> /// 区 /// </summary> public string area { get; set; } /// <summary> /// 全称 /// </summary> public string fullname { get; set; } /// <summary> /// 组织机构代码 /// </summary> public string organizationcode { get; set; } public string mobile { get; set; } public int power { get; set; } public bool deletesign { get; set; } } /// <summary> /// 管理范围 /// </summary> //public enum power //{ // 全部 = 0, // 多区 = 1, // 单区 = 2 //} ///// <summary> ///// 账号身份 ///// </summary> //public enum accountrole //{ // 管理登录 = 0, // 普通登录 = 1 //} ///// <summary> ///// 员工身份 ///// </summary> //public enum employeerole //{ // 部门主管 = 0, // 普通员工 = 1 //} }
也可以使用枚举,这里我还是没用了。但是意思就是这么个意思哈哈哈哈。
通过ef建库建表完成之后,是不是觉得终于可以进行激动人心的登录仪式了?
转自:https://www.cnblogs.com/InsufficientLuo/p/InsufficientLuo.html