Home  >  Article  >  Backend Development  >  Asp.net MVC uses knockoutjs to log in and record the user's internal and external network IP and city.

Asp.net MVC uses knockoutjs to log in and record the user's internal and external network IP and city.

高洛峰
高洛峰Original
2017-02-10 17:21:491533browse

This article mainly introduces Asp.net MVC's use of knockoutjs to log in and record the user's internal and external network IP and city (recommended). Friends in need can refer to the following

Preface

I started with the first article, and now I want to start with the login, but I feel there are many things that should be written earlier, such as

1, Route configuration of MVC and Web API, how does the Route configuration of Web API support namespace

2. How to configure Filters (implement security verification, error handling, etc.)

3. Custom Filters, HttpRouteConstraint, ModelBinder and HttpParameterBinding, etc.

These problems have been encountered in my development process, but I feel that every point has to be said too much. If necessary, come back to it later.

Requirements

It’s still the same, we first need to understand what we want to achieve by logging in:

1. Login page ( Username, password, remember me, login button, reset button)

2. Message display (for example, when an error occurs, a certain error is displayed, when logging in, it is displayed as logging in, when the login is successful, it is displayed as jumping, etc.)

3. Login processing (verification, login, disabling the form while logging in, updating user login times and time, adding login history, including the user's internal IP, external IP, city, and other business processing)

4. Successful jump

Achievement effect

Before implementing it, let’s take a look at the screenshot of the effect

Login page

Asp.net MVC利用knockoutjs实现登陆并记录用户的内外网IP及所在城市

Jump page

Asp.net MVC利用knockoutjs实现登陆并记录用户的内外网IP及所在城市

##Login resume

Asp.net MVC利用knockoutjs实现登陆并记录用户的内外网IP及所在城市

Requirement analysis and implementation

The requirements are basically easy to implement. Only the internal and external network IP and the city where the login history is located need to be considered. one time. It is quite troublesome to obtain the client's internal and external network IP in asp.NET, but it is basically impossible to obtain the city, so we have to consider using a third-party API to achieve it.

1. The internal IP is obtained directly in the background.

2. The external IP can be obtained through Sina API http://counter.sina.com.cn/ip. It can also be returned to the city. Yes, the background can only return IP for unknown reasons

3. The city is obtained through Baidu API http://api.map.baidu.com/location/ip?ak=&ip, but this cannot It will return the external IP, so I used both of them together, which was quite painful.

There is a cross-domain problem when the client accesses the corresponding API. Through investigation, it was found that Baidu API supports JSONP, which can solve cross-domain problems very well. Sina API does not support it but it returns a variable. , we can directly write the Sina API in the page script to obtain the corresponding variables.

The technology should be fine, so let’s start writing.

Specific implementation

Step one: Create a new LoginController in MVC and add the following code

using System;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Zephyr.Core;
using Zephyr.Models;
using Zephyr.Web.Areas.Mms.Common;
namespace Zephyr.Controllers
{
 [AllowAnonymous]
 public class LoginController : Controller
 {
 public ActionResult Index()
 {
 ViewBag.CnName = "建筑材料管理系统";
 ViewBag.EnName = "Engineering Material Mangange System";
 return View();
 }
 }
}

The class must be modified with the AllowAnonymous attribute to ensure that it can be accessed even if you are not logged in.

Step 2: Add the corresponding View, add ~/Views/Login/Index.cshtml, the code is as follows

@{
 ViewBag.Title = "登录系统";
 Layout = null;
}
<!doctype html>
<html>
 <head>
 <title>@ViewBag.Title</title>
 <link href="~/Content/css/page/login.css" rel="stylesheet" type="text/css" />
 <script src="~/Content/js/jquery/jquery-1.8.1.min.js"></script>
 <script src="~/Content/js/core/json2.js"></script>
 <script src="~/Content/js/core/knockout-2.2.1.js"></script>
 <script src="~/Content/js/viewModel/login.js"></script>
 <script src="http://counter.sina.com.cn/ip"></script>
 </head>
 <body>
 <p class="second_body">
 <form data-bind="submit:loginClick">
 <p class="logo"><img src="/Content/images/login/logo.png" alt="" /></p>
 <p class="title-zh">@ViewBag.CnName</p>
 <p class="title-en" style="@ViewBag.EnNameStyle">@ViewBag.EnName</p>
 <p class="message" data-bind="html:message"></p>
 <table border="0" style="width:300px;">
  <tr>
  <td style="padding-bottom: 5px;width:55px;">用户名:</td>
  <td colspan="2"><input type="text" class="login" data-bind="value:form.usercode" /></td>
  </tr>
  <tr>
  <td class="lable" style="letter-spacing: 0.5em; vertical-align: middle">密码:</td>
  <td colspan="2"><input type="password" class="login" data-bind="value:form.password" /></td>
  </tr>
  <tr>
  <td></td>
  <td colspan="2"><input type="checkbox" data-bind="checked:form.remember" /><span>系统记住我</span></td>
  </tr>
  <tr>
  <td colspan="3" style="text-align:center">
  <input type="submit" value="登录" class="login_button" />
  <input type="button" value="重置" class="reset_botton" data-bind="click:resetClick" />
  </td>
  </tr>
 </table>
 </form>
 </p>
 </body>
</html>

1. Script The last one is to add Sina API to obtain external network IP information. The data format it returns is

var ILData = new Array("117.30.94.103","保留地址", "", "", ""); if (typeof(ILData_callback) != "undefined") { ILData_callback(); }

. It actually also has a callback function, which is similar to JSONP, but The function name is fixed and no data is passed. We can directly access ILData[0] to obtain the external network IP.

2. The data-bind="" in the above html is written in the knouckoutjs way, which is used to bind to the properties of the viewModel

Step 3: Create the ViewModel

var viewModel = function () {
 var self = this;
 this.form = {
 usercode: ko.observable(),
 password: ko.observable(),
 remember:ko.observable(false),
 ip: null,
 city: null
 };
 this.message = ko.observable();
 this.loginClick = function (form) {
 $.ajax({
 type: "POST",
 url: "/login/doAction",
 data: ko.toJSON(self.form),
 dataType: "json",
 contentType: "application/json",
 success: function (d) {
 if (d.status == &#39;success&#39;) {
  self.message("登陆成功正在跳转,请稍候...");
  window.location.href = &#39;/&#39;;
 } else {
  self.message(d.message);
 }
 },
 error: function (e) {
 self.message(e.responseText);
 },
 beforeSend: function () {
 $(form).find("input").attr("disabled", true);
 self.message("正在登陆处理,请稍候...");
 },
 complete: function () {
 $(form).find("input").attr("disabled", false);
 }
 });
 };
 this.resetClick = function () {
 self.form.usercode("");
 self.form.password("");
 self.form.remember(false);
 };
 this.init = function () {
 self.form.ip = ILData[0];
 $.getJSON("http://api.map.baidu.com/location/ip?ak=F454f8a5efe5e577997931cc01de3974&callback=?", function (d) {
 self.form.city = d.content.address;
 });
 if (top != window) top.window.location = window.location;
 };
 this.init();
};
$(function () { ko.applyBindings(new viewModel());});

Define viewModel, its attributes include from form information, message prompt information, loginClick login, resetClick reset. The init part actually does not need to be placed in the viewModel.

1. $.getJSON is the access to JSONP, with the parameter callback=? added. jQuery will automatically process it into the current callback function, that is, after the cross-domain is successful, it will automatically call back the current function and pass in the data. . We use form.city in viewModel to receive the city information in the requested data.

2、最后一句ko.applyBindings(new viewModel())即实现了页面和viewModel的绑定,至此,前台全部完成。接下来写登陆处理doAction,还是放在LoginController中,访问地址为/login/doAction。

第四步:在LoginController中添加doAction的方法返回JSON数据。代码如下:

public JsonResult DoAction(JObject request)
{
 var message = new sys_userService().Login(request);
 return Json(message, JsonRequestBehavior.DenyGet);
}

然后在service层中处理

using System;
using System.Collections.Generic;
using Zephyr.Core;
using System.Dynamic;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Zephyr.Utils;
using Zephyr.Web.Areas.Mms.Common;
namespace Zephyr.Models
{
 public class sys_userService : ServiceBase<sys_user>
 {
 public object Login(JObject request) 
 {
 var UserCode = request.Value<string>("usercode");
 var Password = request.Value<string>("password");
 //用户名密码检查
 if (String.IsNullOrEmpty(UserCode) || String.IsNullOrEmpty(Password))
 return new { status = "error", message = "用户名或密码不能为空!" };
 //用户名密码验证
 var result = this.GetModel(ParamQuery.Instance()
  .AndWhere("UserCode", UserCode)
  .AndWhere("Password", Password)
  .AndWhere("IsEnable", true));
 if (result == null || String.IsNullOrEmpty(result.UserCode))
 return new { status = "error", message = "用户名或密码不正确!" };
 //调用框架中的登陆机制
 var loginer = new LoginerBase { UserCode = result.UserCode, UserName = result.UserName };
 FormsAuth.SignIn(loginer.UserCode, loginer, 60 * 8); 
 //登陆后处理
 this.UpdateUserLoginCountAndDate(UserCode); //更新用户登陆次数及时间
 this.AppendLoginHistory(request); //添加登陆履历
 MmsService.LoginHandler(request); //MMS系统的其它的业务处理
 //返回登陆成功
 return new { status = "success", message = "登陆成功!" };
 }
 //更新用户登陆次数及时间
 public void UpdateUserLoginCountAndDate(string UserCode)
 {
 db.Sql(@"
update sys_user
set LoginCount = isnull(LoginCount,0) + 1
 ,LastLoginDate = getdate()
where UserCode = @0 "
 , UserCode).Execute();
 }
 //添加登陆履历
 public void AppendLoginHistory(JObject request)
 {
 var lanIP = ZHttp.ClientIP;
 var hostName = ZHttp.IsLanIP(lanIP) ? ZHttp.ClientHostName : string.Empty; //如果是内网就获取,否则出错获取不到,且影响效率
 var UserCode = request.Value<string>("usercode");
 var UserName = MmsHelper.GetUserName();
 var IP = request.Value<string>("ip");
 var City = request.Value<string>("city");
 if (IP != lanIP)
 IP = string.Format("{0}/{1}", IP, lanIP).Trim(&#39;/&#39;).Replace("::1", "localhost");
 var item = new sys_loginHistory();
 item.UserCode = UserCode;
 item.UserName = UserName;
 item.HostName = hostName;
 item.HostIP = IP;
 item.LoginCity = City;
 item.LoginDate = DateTime.Now;
 db.Insert<sys_loginHistory>("sys_loginHistory", item).AutoMap(x => x.ID).Execute();
 }
 }
}

接收参数定义为JObject对象比较方便取得请求数据,数据服务中的GetModel是服务基类中已有的方法,这当中用到了两个函数,一个为UpdateUserLoginCountAndDate为更新用户登陆次数及时间的处理,另一个AppendLoginHistory添加登陆履历。至此已大功告成!

以上所述是小编给大家介绍的Asp.net MVC利用knockoutjs实现登陆并记录用户的内外网IP及所在城市(推荐),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网的支持!

更多Asp.net MVC利用knockoutjs实现登陆并记录用户的内外网IP及所在城市相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn