前面我们已经做好了一个文章管理功能模块,接下来,我们回头来做登录窗口,登录不仅涉及到登录验证还涉及到登录日志还有缓存时长等。

对于缓存的相关设置,我们已经写好封装在Bobo.Utilities.dll程序集中,我们只需要引用就好,没有的,请到此处下载

在实现之前,我们需要先在表现层创建一个Resource文件夹,用于存放我们公共的文件、图片及模板等,然后下载

IPScaner.zip,并加压到Resource文件夹下。

    QQwry.dat 纯真IP数据库收集了包括中国电信、中国网通、长城宽带、网通宽带、聚友宽带等 ISP 的最新准确 IP 地址数据。目前该库不是最新的数据,大家可以到网上下载到该目录下,这在我们做登录日志时可用到。

一、我们在区域BackstageModule下创建Login的控制器和视图:

(1)LoginController.cs控制器

using Bobo.Utilities;
using Bobo.Utilities.Membership;
using IA.Business.SystemBusiness;
using IA.Entity;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace IA.WebApp.Areas.BackstageModule.Controllers
{
/// <summary>
/// 后台登录控制器
/// </summary>
public class LoginController : Controller
{
//
// GET: /BackstageModule/Login/ public ActionResult Index()
{
return View();
}
/// <summary>
/// 登录
/// </summary>
/// <param name="Account"></param>
/// <param name="Password"></param>
/// <param name="Code"></param>
/// <returns></returns>
public ActionResult SubmitLogin(string Account, string Password, string Code)
{
try
{
Code = Md5Helper.CreateMd5(Code.ToLower(), 16);
if (Session["session_Userloginvcode"].ToString() != Code)
{
return Content(new JsonMessage { Success = false, Code = "-2", Message = "验证码不正确" }.ToString());
}
if (string.IsNullOrEmpty(Account) || string.IsNullOrEmpty(Password))
{
return Content(new JsonMessage { Success = false, Code = "-1", Message = "用户名或密码错误!" }.ToString());
}
IPScanerHelper objScan = new IPScanerHelper();
string IPAddress = NetHelper.LANIP;
objScan.IP = IPAddress;
objScan.DataPath = Server.MapPath("~/Resource/IPScaner/QQWry.Dat");
string IPAddressName = objScan.IPLocation(); int IsOk = new Base_UserBll().UserLogin(Account, Password, IPAddressName, IPAddress);
string strCode = "-1";
string Message = "";
string czMsg = "";
bool Success = false;
switch (IsOk)
{
case 1:
strCode = "1";
Message = "登录成功!";
czMsg = "登录成功!";
Success = true;
break;
case 2:
strCode = "-1";
Message = "登录失败,用户名或密码错误!";
czMsg = "密码错误!";
Success = false;
break;
case 3:
strCode = "-1";
Message = "登录失败,用户名或密码错误!";
czMsg = "账号不存在!";
Success = false;
break;
}
Base_SysLogBll.Instance.WriteLog(Account, OperationType.Login, strCode, czMsg + "、IP所在城市:" + IPAddressName);
return Content(new JsonMessage { Success = Success, Code = strCode, Message = Message }.ToString());
}
catch (Exception ex)
{
return Content(new JsonMessage { Success = false, Code = "-1", Message = "操作失败:" + ex.Message }.ToString());
} }
/// <summary>
/// 验证码
/// </summary>
/// <returns></returns>
public ActionResult VerifyCode()
{
int codeW = 80;
int codeH = 22;
int fontSize = 16;
string chkCode = string.Empty;
//颜色列表,用于验证码、噪线、噪点
Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue };
//字体列表,用于验证码
string[] font = { "Times New Roman", "Verdana", "Arial", "Gungsuh", "Impact" };
//验证码的字符集,去掉了一些容易混淆的字符
char[] character = { '2', '3', '4', '5', '6', '8', '9', 'a', 'b', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
Random rnd = new Random();
//生成验证码字符串
for (int i = 0; i < 4; i++)
{
chkCode += character[rnd.Next(character.Length)];
}
//写入Session、验证码加密
Session["session_Userloginvcode"] = Md5Helper.MD5(chkCode.ToLower(), 16);
//创建画布
Bitmap bmp = new Bitmap(codeW, codeH);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White);
//画噪线
for (int i = 0; i < 1; i++)
{
int x1 = rnd.Next(codeW);
int y1 = rnd.Next(codeH);
int x2 = rnd.Next(codeW);
int y2 = rnd.Next(codeH);
Color clr = color[rnd.Next(color.Length)];
g.DrawLine(new Pen(clr), x1, y1, x2, y2);
}
//画验证码字符串
for (int i = 0; i < chkCode.Length; i++)
{
string fnt = font[rnd.Next(font.Length)];
Font ft = new Font(fnt, fontSize);
Color clr = color[rnd.Next(color.Length)];
g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr), (float)i * 18 + 2, (float)0);
}
//将验证码图片写入内存流,并将其以 "image/Png" 格式输出
MemoryStream ms = new MemoryStream();
try
{
bmp.Save(ms, ImageFormat.Png);
return File(ms.ToArray(), @"image/Gif");
}
catch (Exception)
{
return null;
}
finally
{
g.Dispose();
bmp.Dispose();
}
} /// <summary>
/// 退出当前登录,清空所有用户cookie
/// </summary>
/// <returns></returns>
public ActionResult LoginOut()
{
/*****************************************
* 采用双cookie登录,则需要释放双cookie
* 标准cookie记录用户主要信息,附加cookie用于前台
* 附加cookie可记录自定义的任何信息
* ***************************************/
//清空当前登录用户信息
ManageProvider.Provider.EmptyCurrent();
ManageProvider.Provider.EmptyCurrent<Base_User>();
Session.Abandon(); //取消当前会话
Session.Clear(); //清除当前浏览器所以Session
return Content("1");
}
}
}

(2)Index视图

@{
ViewBag.Title = "登录"; }
<script src="~/Content/Scripts/jquery/jquery-1.8.2.min.js"></script>
<script src="~/Content/Scripts/jquery.form.js"></script>
<script src="~/Content/Scripts/boboui-jshelp.js"></script>
<script src="~/Content/Scripts/validator/boboui-validator.js"></script>
<script src="~/Content/Scripts/layer/layer.js"></script>
<script src="~/Content/Scripts/jQuery.md5.js"></script>
<link href="~/Content/Styles/base.css" rel="stylesheet" />
<link href="~/Content/Styles/main.css" rel="stylesheet" />
<body style="background-color: #4e95e5; " class="font-yahei">
<div class="mainBox">
<h1 style="text-align: center; font-weight: bold; font-size:24px; color: #fff; padding-bottom: 25px; letter-spacing: 2px;">枼落NO.1</h1>
<div class="Dialog-Box BoxS" style="margin: 0 auto; max-width: 500px; max-height: 300px; background-color: #fff; border-radius: 4px; padding: 0;">
<div class="Dialog-Tit-com" style="position:relative">系统用户登录</div>
<div class="login-Ico L"><img src="~/Content/Images/slice/users_03.png" width="78" height="76" /> </div>
<div class="login-box L">
<form id="form1" action="/BackstageModule/Login/SubmitLogin" method="post" enctype="multipart/form-data" style="margin: 1px">
<table class="layer-table-form">
<tr>
<td><span class="layer-form-tit">用户名:</span><input style="height:30px;border-radius:4px;" type="text" name="Account" class="layer-form-txt" id="Account" datacol="yes" err="用户名" checkexpession="NotNull" /></td>
</tr>
<tr>
<td><span class="layer-form-tit">密 &nbsp;&nbsp;码:</span><input style="height:30px;border-radius:4px;" type="password" name="Password" class="layer-form-txt" id="Password" datacol="yes" err="密码" checkexpession="NotNull" /></td>
</tr>
<tr>
<td>
<span class="layer-form-tit">验证码:</span><input type="text" name="Code" style="width: 100px; height: 30px; border-radius: 4px; " class="layer-form-txt" id="Code" datacol="yes" err="验证码" checkexpession="NotNull" />
<img id="codeImg" src="/BackstageModule/Login/VerifyCode" data-url="/BackstageModule/Login/VerifyCode" alt="点击切换验证码" onclick="switchCode($(this))" />
</td>
</tr>
</table>
</form>
</div>
<div class="Dialog-sub-com" style="position:relative">
<input type="button" value="登录" class="Dialog-btn subBtn" onclick="AcceptClick()">
<input type="button" value="取消" class="Dialog-btn extBtn" onclick="selfClose()">
</div>
</div>
</div>
<div class="clear" style="position:fixed;bottom:10px;color:#fff;text-align:center;width:100%;">页落素材网 Copyright 2008-2018 All Rights Reserved</div>
</body> <script type="text/javascript">
//提交表单
function AcceptClick() {
if (!CheckDataValid('#form1', true)) {
return false;
} var postData = GetWebControls("#form1");
postData.Password = escape($.md5(postData.Password));
$.post("/BackstageModule/Login/SubmitLogin?Code=" + $("#Code").val(), postData, function (data) {
layer.msg(data.Message, { icon: data.Code, time: 1000 }, function () {
if (data.Code > 0) {
selfClose();
location.href = "/BackstageModule/ArticleMange/Index";
}
else if (data.Code == -2) {
$("#Code").val("").focus();
switchCode($("#codeImg"));
}
});
}, "json");
}
//回车键
document.onkeydown = function (e) {
if (!e) e = window.event; //火狐中是 window.event
if ((e.keyCode || e.which) == 13) {
AcceptClick();
}
}
//自定义关闭窗口
function selfClose() {
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
}
//切换验证码
function switchCode(obj) {
var url = obj.attr("data-url");
url += "?date=" + new Date().toString();
obj.attr("src", url);
}
</script>

二、在完成登录操作的过程后,我们需要对登录权限的认证,也就是非登录不可访问。

首先我们需要在表现层中的SystemExtension文件夹中添加LoginAuthorizeAttribute.cs和ManagerPermissionAttribute.cs登录权限类:

(1)LoginAuthorizeAttribute.cs

using Bobo.Utilities;
using Bobo.Utilities.Membership;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace IA.WebApp.SystemExtension
{
/// <summary>
/// 登录权限认证
/// </summary>
public class LoginAuthorizeAttribute : AuthorizeAttribute
{
//地址参数的绝对路径("~/aaa/vvv")
private String _LoginUrl = String.Empty;
//无参构造器
public LoginAuthorizeAttribute() { } /// <summary>
/// 标记构造器,可传入登陆地址
/// </summary>
/// <param name="LoginUrl">地址参数的绝对路径("~/aaa/vvv")</param>
public LoginAuthorizeAttribute(string LoginUrl)
{
this._LoginUrl = LoginUrl;
}
/// <summary>
/// 响应前执行验证,查看当前用户是否有效
/// </summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
var areaName = filterContext.RouteData.DataTokens["area"];
var controllerName = filterContext.RouteData.Values["controller"];
var action = filterContext.RouteData.Values["Action"];
var returnUrl = filterContext.RequestContext.HttpContext.Request.Url.ToString();
if (!StringHelper.IsNullOrEmpty(this._LoginUrl) && this._LoginUrl.IndexOf('?') == -1)
{
this._LoginUrl += ("?ReturnUrl=" + StringHelper.Escape(returnUrl));
}
if (this._LoginUrl.IndexOf("BackstageModule") != -1)
{
if (!ManageProvider.Provider.IsOverdue())
{
filterContext.Result = new RedirectResult(this._LoginUrl);
}
else
{
if (ManageProvider.Provider.Current().Code != "System")
{
filterContext.Result = new RedirectResult(this._LoginUrl);
}
}
}
else
{ //登录是否过期
if (!ManageProvider.Provider.IsOverdue())
{
filterContext.Result = new RedirectResult(this._LoginUrl);
}
else
{
if (ManageProvider.Provider.Current().Code == "System")
{
filterContext.Result = new RedirectResult(this._LoginUrl);
}
}
}
}
}
}

(2)ManagerPermissionAttribute.cs

using Bobo.Utilities;
using Bobo.Utilities.Membership;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace IA.WebApp.SystemExtension
{
public class ManagerPermissionAttribute : AuthorizeAttribute
{
private PermissionMode _CustomMode;
/// <summary>默认构造</summary>
/// <param name="Mode">权限认证模式</param>
public ManagerPermissionAttribute(PermissionMode Mode)
{
_CustomMode = Mode;
}
/// <summary>权限认证</summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
//登录权限认证
if (!ManageProvider.Provider.IsOverdue())
{
filterContext.Result = new RedirectResult("~/Login/Default");
}
//防止被搜索引擎爬虫、网页采集器
if (!this.PreventCreeper())
{
filterContext.Result = new RedirectResult("~/Login/Default");
}
//权限拦截是否忽略
if (_CustomMode == PermissionMode.Ignore)
{
return;
}
//执行权限认证
if (!this.ActionAuthorize(filterContext))
{
ContentResult Content = new ContentResult();
Content.Content = "<script type='text/javascript'>top.Loading(false);alert('很抱歉!您的权限不足,访问被拒绝!');</script>";
filterContext.Result = Content;
}
}
/// <summary>
/// 执行权限认证
/// </summary>
/// <returns></returns>
private bool ActionAuthorize(AuthorizationContext filterContext)
{
if (ManageProvider.Provider.Current().IsSystem && ManageProvider.Provider.Current().CompanyCategory != "SystemUnit")
return true;
var areaName = filterContext.RouteData.DataTokens["area"] + "/"; //获取当前区域
var controllerName = filterContext.RouteData.Values["controller"] + "/"; //获取控制器
var action = filterContext.RouteData.Values["Action"]; //获取当前Action
string requestPath = "/" + areaName + controllerName + action; //拼接构造完整url
string ModuleId = DESEncrypt.Decrypt(CookieHelper.GetCookie("ModuleId"));
//bool Result = Base_ModulePermissionBll.Instance.ActionAuthorize(requestPath.ToLower(), ManageProvider.Provider.Current().ObjectId, ModuleId, ManageProvider.Provider.Current().UserId);
return true;// Result;
}
/// <summary>
/// CA验证方法
/// </summary>
/// <param name="filterContext"></param>
/// <returns></returns>
private bool ActionCA(AuthorizationContext filterContext)
{
//TODO:如何在过滤器调用CA的前台检测方法返回值(NC)
if (ManageProvider.Provider.Current().IsSystem && ManageProvider.Provider.Current().CompanyCategory != "SystemUnit")
{
return true;
}
else
{
return true;
}
}
/// <summary>
/// 防止被搜索引擎爬虫、网页采集器
/// </summary>
/// <returns></returns>
private bool PreventCreeper()
{
return true;
}
}
}

权限认证做好后,我们在需要权限认证的控制器上加上[LoginAuthorize("~/BackstageModule/Login/Index")]这句了,例如文章控制器:

然后改造公共布局页_LayoutMange.cshtml:

@using Bobo.Utilities.Membership
@using IA.Business
<!DOCTYPE html>
<html>
@*后台公共模块*@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" media="screen" />
<link href="~/Content/Styles/main.css" rel="stylesheet" />
<link href="~/Content/Styles/base.css" rel="stylesheet" />
<script src="~/Content/Scripts/datepicker/WdatePicker.js"></script>
<script src="~/Content/Scripts/jquery/jquery-1.8.2.min.js"></script>
<script src="~/Content/Scripts/jquery.form.js"></script>
<script src="~/Content/Scripts/boboui-jshelp.js"></script>
<script src="~/Content/Scripts/validator/boboui-validator.js"></script>
<script src="~/Content/Scripts/layer/layer.js"></script>
<script src="~/Content/Scripts/Juicer/juicer.js"></script>
<script src="~/Content/Scripts/m_pager.js"></script>
</head>
<body class="set_body">
<div class="w_header font-yahei">
<div class="header-item">
<div class="mAuto">
<div class="L">页落素材网 - 用户管理后台 【当前用户】:@ManageProvider.Provider.Current().UserName</div>
<div class="R"><a href="javascript:;" id="LoginOut" style="color: #00b7f0;">【退出登录】</a></div>
</div>
</div>
<div class="header-nav clear">
<div class="mAuto">
<a href="/" class="logo L"> <img src="~/Content/Images/slice/logoMange.png" /></a>
<ul class="R nav-item">
<li class="L"><a href="/BackstageModule/Article/Index" class="wzgl">网站管理</a></li>
<li class="L"><a href="/BackstageModule/TrainSignupInfo/Index" class="hypx">区块链</a></li>
<li class="L"><a href="/BackstageModule/MemberManagement/Index" class="hygl">人工智能</a></li>
<li class="L"><a href="/">返回首页</a></li>
</ul>
</div>
</div>
</div> @RenderBody()
<div id="footer">
<div class="foot-tip w_footer">
<div class="webPage text-center">
页落素材网是网页特效下载社区,以提高效率、分享经验的理念,提供高品质实用、简单、易懂的Web页面特效。
</div>
</div>
</div> <script type="text/javascript">
$(function () {
$("#LoginOut").on("click", function () {
AjaxJson("/BackstageModule/Login/LoginOut", {}, function (data) {
layer.msg("您已退出登录,欢迎再来哦 ^_^", { icon: 6, shade: [0.3, '#000'] }, function () {
location.href = "/BackstageModule/Login/Index";
});
});
});
})
//复选框选定事件
function change(obj) {
var tr = obj.parentElement.parentElement;
if (obj.checked) {
tr.style.backgroundColor = '#e5eaff';
tr.style.borderColor = '#cacccb';
} else {
tr.style.backgroundColor = '#fff';
}
}
</script>
@RenderSection("scripts", required: false)
</body>
</html>

登录效果图预览

ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(9)之系统登录的更多相关文章

  1. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(13)之会员登录注册

    源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 会员中心,是我们与用户交 ...

  2. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(1)之数据库设计

    本文主要讲解本项目网站所应用到的知识点,及数据库的相关设计: 一.知识点 (1)本项目主要采取ASP.NET MVC的编程模式,相信你已经了解到了MVC的具体含义是什么,这里不再赘述,有不了解的朋友, ...

  3. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(16)之轻博客

    源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 项目到上面一步其实已经算 ...

  4. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(15)之前台网站页面

    源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 本项目主要是一个素材的分 ...

  5. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(14)之会员中心管理

    源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 会员中心,主要包含了会员 ...

  6. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(7)之扩展基类和区域创建以及文本编辑配置

    一.扩展基类和区域创建 (1)在应用之前,我们先在表现层创建一个公共的系统扩展文件来(SystemExtension)存放我们需要延伸和扩展的方法类. 在常规的项目系统操作中,我们都需要用到增删查改的 ...

  7. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(2)之创建项目

    我们在创建项目的时候一定要遵循层次和命名的原则,同时也要有统一的规范,无论是多人项目还是单人项目,能够让人看着一目了然并赏析悦目,做一个有追求的程序员. 例如IA.WebApp是视图控制器层(表现层) ...

  8. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(8)之文章管理

    到这一步,我们整个项目的核心搭建已经算是完成了,接下来就是我们业务功能的实际应用,也就是表现层的设计和实现,如果你是一个项目负责人,到这一步,接下来的工作就可以交给下面的兄弟去完成了,在这里我们用文章 ...

  9. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(11)之支付管理及广告管理

    源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 本项目属于个人项目,不支 ...

随机推荐

  1. 洛谷2050 BZOJ2897美食节题解

    放个链接 BZ链接 其实这题就是修车的加强版,做法差不多,还是对于每个厨师进行拆点 可是这样强行建图跑网络流会T飞 我们发现,如果一个厨师没有做倒数第x到菜,他一定不会做倒数第x+1到菜 我们的每次增 ...

  2. MySQL命令行分号无法结束问题解决

    背景:输入一串查询语句,以分号结束,发现没有结束,再打回车,分号,还是不完.什么exit,quit,bye,都不顶用如果要ctrl+C吧,又得退出mysql,一切重来,很麻烦.后来终于发现,引起这种现 ...

  3. HDU-1160_FatMouse's Speed

    FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Sp ...

  4. BZOJ 1008 越狱题解

    其实这题很水,显然n个房间有m种宗教,总共有n^m种情况, 我们再考虑不合法的情况,显然第一个房间有m种情况,而后一种只有m-1种情况(因为不能相同) 所以不合法的情况有(m-1)^(n-1)*m种情 ...

  5. 提高webpack的构建速度的几种方法概括

    通过externals配置来提取常用库 利用DllPlugin和DllReferencePlugin预编译资源模块,通过DllPlugin来对那些我们引用但是绝对不会修改的npm包来进行预编译,再通过 ...

  6. HLSL效果框架-多光源效果

    原文:HLSL效果框架-多光源效果 昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 手机淘宝二维码 扫描       或者打开连接:程序设计开发 ,掌声鼓励,欢迎光临.     高级着色器语言(HLS ...

  7. 关于使用 Java 分片读\写文件

    分片读取文件方法: /** * 分片读取文件块 * * @param path 文件路径 * @param position 角标 * @param blockSize 文件块大小 * @return ...

  8. Java练习 SDUT-2761_编码

    编码 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给你一个由大写字母组成的组成的字符串,你可以用如下规则对其进行编码 ...

  9. 01docker简单使用和配置(容器、镜像)

    一:容器中运行简单应用程序 1:hello  world 使用docker可以在容器中运行应用程序,使用docker run命令即可.比如下面的命令: $ docker run ubuntu /bin ...

  10. 1 项目里面如何打印log日志

    1  首先写一个logging.py文件 import logging from conf import setting #配置文件,里面有日志存放路径 def mylog(): logger = l ...