WebApi实现验证授权Token,WebApi生成文档等
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
using System; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Security; namespace OtherApi.Auth { public class AuthFilterOutside : AuthorizeAttribute { //重写基类的验证方式,加入我们自定义的Ticket验证 public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) { //url获取token var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase; var token = content.Request.Headers["Token"]; if (!string.IsNullOrEmpty(token)) { //解密用户ticket,并校验用户名密码是否匹配 if (ValidateTicket(token)) { base.IsAuthorized(actionContext); } else { HandleUnauthorizedRequest(actionContext); } } //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401 else { var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>(); bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); if (isAnonymous) base.OnAuthorization(actionContext); else HandleUnauthorizedRequest(actionContext); } } //校验票据(数据库数据匹配) private bool ValidateTicket(string encryptToken) { bool flag = false; try { //获取数据库Token Dec.Models.TicketAuth model = Dec.BLL.TicketAuth.GetTicketAuthByToken(encryptToken); if (model.Token == encryptToken) //存在 { //未超时 flag = (DateTime.Now <= model.ExpireDate) ? true : false; } } catch (Exception ex) { } return flag; } } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
using System; using System.Web; using System.Web.Http; using System.Web.Security; using System.Net.Http; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Text; using OtherApi.Auth; //引用验证 namespace SpiderApi.Controllers { /// <summary> /// 用户授权接口 /// </summary> public class AccountController : ApiController { #region 用户登录授权 /// <summary> /// 用户登录授权 /// </summary> /// <param name="username">用户名</param> /// <param name="password">密码</param> /// <returns></returns> [Route("api/account/login")] [HttpGet] public HttpResponseMessage Login(string username, string password) { //定义 ResponseResult obj = new ResponseResult(); var model = GetLoginModel(username, password); if (model != null) { int userId = model.UserId; string Token = UntilHelper.Md5Encode(UntilHelper.GetExtGuidID(), 32); var dtNow = DateTime.Now; #region 将身份信息保存票据表中,验证当前请求是否是有效请求 //判断此用户是否存在票据信息 if (Dec.BLL.TicketAuth.GetTicketAuthByUserId(userId) != null) { //清空重置 Dec.BLL.TicketAuth.DeleteByUserId(userId); } Dec.Models.TicketAuth ticket = new Dec.Models.TicketAuth(); ticket.UserID = userId; ticket.Token = Token; ticket.CreateDate = dtNow; ticket.ExpireDate = dtNow.AddMinutes(30); //30分钟过期 Dec.BLL.TicketAuth.Add(ticket); #endregion //返回信息 obj.status = true; obj.message = "用户登录成功"; JObject jo = new JObject(); jo.Add("userid", userId); jo.Add("loginname", model.LoginName); jo.Add("nickname", model.NickName); jo.Add("usertype", model.UserType); //(int)UserTypeEnum.Seller jo.Add("token", Token); obj.info = jo; } else { obj.status = false; obj.message = "用户登录失败"; } var resultObj = JsonConvert.SerializeObject(obj, Formatting.Indented); HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(resultObj, Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } #endregion #region 用户退出登录,清空Token /// <summary> /// 用户退出登录,清空Token /// </summary> /// <param name="userId">用户ID</param> /// <returns></returns> [Route("api/account/loginout")] [HttpGet] public HttpResponseMessage LoginOut(int userId) { //定义 ResponseResult obj = new ResponseResult(); try { //清空数据库该用户票据数据 Dec.BLL.TicketAuth.DeleteByUserId(userId); } catch (Exception ex) { } //返回信息 obj.status = true; obj.message = "成功退出"; var resultObj = JsonConvert.SerializeObject(obj); HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(resultObj, Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } #endregion #region 查询Token是否有效 /// <summary> /// 查询Token是否有效 /// </summary> /// <param name="token">token</param> /// <returns></returns> [Route("api/account/validatetoken")] [HttpGet] public HttpResponseMessage ValidateToken(string token) { //定义 ResponseResult obj = new ResponseResult(); bool flag = ValidateTicket(token); if (flag) { //返回信息 obj.status = true; obj.message = "token有效"; } else { obj.status = false; obj.message = "token无效"; } var resultObj = JsonConvert.SerializeObject(obj); HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(resultObj, Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } #endregion #region 获取用户账户余额 /// <summary> /// 获取用户账户余额 /// </summary> /// <param name="userId">用户ID</param> /// <returns></returns> [Route("api/account/amount")] [HttpGet] [AuthFilterOutside] //添加验证 public HttpResponseMessage GetAmount(int userId) { //定义 ResponseResult obj = new ResponseResult(); //获取数据库数据 Dec.Models.UserInfo model = Dec.BLL.UserInfo.GetUserInfoByUserId(userId); if (model != null) { //返回信息 obj.status = true; obj.message = "获取用户账户余额成功"; JObject jo = new JObject(); jo.Add("userid", model.UserId); jo.Add("amount", model.Amount); obj.info = jo; } else { obj.status = false; obj.message = "获取用户账户余额失败"; } var resultObj = JsonConvert.SerializeObject(obj); HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(resultObj, Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } #endregion /// <summary> /// 用户充值接口 /// </summary> /// <param name="userid">用户ID</param> /// <param name="amount">充值金额</param> /// <returns></returns> [Route("api/account/recharge")] [HttpGet] [AuthFilterInside] public HttpResponseMessage Recharge(string userid, double amount) { //定义 ResponseResult obj = new ResponseResult(); //获取数据库数据 //返回信息 obj.status = true; obj.message = "操作成功,请等待第三方支付平台返回通知核实是否到账"; JObject jo = new JObject(); jo.Add("userid", "123456789"); jo.Add("amount", 125.80); obj.info = jo; var resultObj = JsonConvert.SerializeObject(obj); HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(resultObj, Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } #region 验证票据是否有效 /// <summary> /// 验证票据是否有效 /// </summary> /// <param name="encryptToken">token</param> /// <returns></returns> private bool ValidateTicket(string encryptToken) { bool flag = false; try { //获取数据库Token Dec.Models.TicketAuth model = Dec.BLL.TicketAuth.GetTicketAuthByToken(encryptToken); if (model.Token == encryptToken) //存在 { //未超时 flag = (DateTime.Now <= model.ExpireDate) ? true : false; } } catch (Exception ex) { } return flag; } #endregion #region 用户登录 /// <summary> /// 用户登录 /// </summary> /// <param name="userName">用户名</param> /// <param name="userPwd">密码</param> /// <returns></returns> private Dec.Models.UserInfo GetLoginModel(string userName, string userPwd) { Dec.Models.UserInfo model = new Dec.Models.UserInfo(); try { if (!string.IsNullOrWhiteSpace(userName) && !string.IsNullOrWhiteSpace(userPwd)) { //数据库比对 model = Dec.BLL.UserInfo.GetUserInfoByUserNamePwd(userName, UntilHelper.Md5Encode(userPwd, 32)); } } catch (Exception ex) { } return model; } #endregion } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
////////////////////////////////////////////////////////////////// using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; namespace SpiderApi { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { //WebApi文档 AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); } protected void Application_PostAuthorizeRequest() { //Enable Session HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); } } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
// Uncomment the following to provide samples for PageResult<T>. Must also add the Microsoft.AspNet.WebApi.OData // package to your project. 先安装Help Page包 HelpPage=>App_start=>HelpPageConfig.cs ////#define Handle_PageResultOfT using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net.Http.Headers; using System.Reflection; using System.Web; using System.Web.Http; using SpiderApi.Models; #if Handle_PageResultOfT using System.Web.Http.OData; #endif namespace SpiderApi.Areas.HelpPage { /// <summary> /// Use this class to customize the Help Page. /// For example you can set a custom <see cref="System.Web.Http.Description.IDocumentationProvider"/> to supply the documentation /// or you can provide the samples for the requests/responses. /// </summary> public static class HelpPageConfig { [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "SpiderApi.Areas.HelpPage.TextSample.#ctor(System.String)", Justification = "End users may choose to merge this string with existing localized resources.")] [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "bsonspec", Justification = "Part of a URI.")] public static void Register(HttpConfiguration config) { //// Uncomment the following to use the documentation from XML documentation file. //开启解析 config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/Bin/SpiderApi.XML"))); //// Uncomment the following to use "sample string" as the sample for all actions that have string as the body parameter or return type. //// Also, the string arrays will be used for IEnumerable<string>. The sample objects will be serialized into different media type //// formats by the available formatters. //config.SetSampleObjects(new Dictionary<Type, object> //{ // {typeof(string), "sample string"}, // {typeof(IEnumerable<string>), new string[]{"sample 1", "sample 2"}} //}); //添加映射 config.SetSampleResponse(Sample.BatchSendMessageResponse(), new MediaTypeHeaderValue("text/json"), "MessageQueue", "BatchSendMessage"); config.SetSampleResponse(Sample.BatchReceiveMessageResponse(), new MediaTypeHeaderValue("text/json"), "MessageQueue", "BatchReceiveMessage"); config.SetSampleResponse(Sample.DeleteMessageResponse(), new MediaTypeHeaderValue("text/json"), "MessageQueue", "DeleteMessage"); config.SetSampleResponse(Sample.BatchDeleteMessageResponse(), new MediaTypeHeaderValue("text/json"), "MessageQueue", "BatchDeleteMessage"); config.SetSampleResponse(Sample.ChangeMessageVisibilityResponse(), new MediaTypeHeaderValue("text/json"), "MessageQueue", "ChangeMessageVisibility"); // Extend the following to provide factories for types not handled automatically (those lacking parameterless // constructors) or for which you prefer to use non-default property values. Line below provides a fallback // since automatic handling will fail and GeneratePageResult handles only a single type. #if Handle_PageResultOfT config.GetHelpPageSampleGenerator().SampleObjectFactories.Add(GeneratePageResult); #endif // Extend the following to use a preset object directly as the sample for all actions that support a media // type, regardless of the body parameter or return type. The lines below avoid display of binary content. // The BsonMediaTypeFormatter (if available) is not used to serialize the TextSample object. config.SetSampleForMediaType( new TextSample("Binary JSON content. See http://bsonspec.org for details."), new MediaTypeHeaderValue("application/bson")); //// Uncomment the following to use "[0]=foo&[1]=bar" directly as the sample for all actions that support form URL encoded format //// and have IEnumerable<string> as the body parameter or return type. //config.SetSampleForType("[0]=foo&[1]=bar", new MediaTypeHeaderValue("application/x-www-form-urlencoded"), typeof(IEnumerable<string>)); //// Uncomment the following to use "1234" directly as the request sample for media type "text/plain" on the controller named "Values" //// and action named "Put". //config.SetSampleRequest("1234", new MediaTypeHeaderValue("text/plain"), "Values", "Put"); //// Uncomment the following to use the image on "../images/aspNetHome.png" directly as the response sample for media type "image/png" //// on the controller named "Values" and action named "Get" with parameter "id". //config.SetSampleResponse(new ImageSample("../images/aspNetHome.png"), new MediaTypeHeaderValue("image/png"), "Values", "Get", "id"); //// Uncomment the following to correct the sample request when the action expects an HttpRequestMessage with ObjectContent<string>. //// The sample will be generated as if the controller named "Values" and action named "Get" were having string as the body parameter. //config.SetActualRequestType(typeof(string), "Values", "Get"); //// Uncomment the following to correct the sample response when the action returns an HttpResponseMessage with ObjectContent<string>. //// The sample will be generated as if the controller named "Values" and action named "Post" were returning a string. //config.SetActualResponseType(typeof(string), "Values", "Post"); } #if Handle_PageResultOfT private static object GeneratePageResult(HelpPageSampleGenerator sampleGenerator, Type type) { if (type.IsGenericType) { Type openGenericType = type.GetGenericTypeDefinition(); if (openGenericType == typeof(PageResult<>)) { // Get the T in PageResult<T> Type[] typeParameters = type.GetGenericArguments(); Debug.Assert(typeParameters.Length == 1); // Create an enumeration to pass as the first parameter to the PageResult<T> constuctor Type itemsType = typeof(List<>).MakeGenericType(typeParameters); object items = sampleGenerator.GetSampleObject(itemsType); // Fill in the other information needed to invoke the PageResult<T> constuctor Type[] parameterTypes = new Type[] { itemsType, typeof(Uri), typeof(long?), }; object[] parameters = new object[] { items, null, (long)ObjectGenerator.DefaultCollectionSize, }; // Call PageResult(IEnumerable<T> items, Uri nextPageLink, long? count) constructor ConstructorInfo constructor = type.GetConstructor(parameterTypes); return constructor.Invoke(parameters); } } return null; } #endif } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
/* API接口测试工具 - WebApiTestClient使用--Nuget引入组件 --A Simple Test Client for ASP.NET Web API */ /* 1、修改Api.cshtml文件 通过上述步骤,就能将组件WebAPITestClient引入进来。下面我们只需要做一件事:打开文件 (根据 Areas\HelpPage\Views\Help) Api.cshtml 并添加以下内容: @Html.DisplayForModel("TestClientDialogs") @Html.DisplayForModel("TestClientReferences") 添加后Api.cshtml文件的代码如下 */ @using System.Web.Http @using WebApiTestClient.Areas.HelpPage.Models @model HelpPageApiModel @{ var description = Model.ApiDescription; ViewBag.Title = description.HttpMethod.Method + " " + description.RelativePath; } <link type="text/css" href="~/Areas/HelpPage/HelpPage.css" rel="stylesheet" /> <div id="body" class="help-page"> <section class="featured"> <div class="content-wrapper"> <p> @Html.ActionLink("Help Page Home", "Index") </p> </div> </section> <section class="content-wrapper main-content clear-fix"> @Html.DisplayForModel() </section> </div> @Html.DisplayForModel("TestClientDialogs") @section Scripts{ <link href="~/Areas/HelpPage/HelpPage.css" rel="stylesheet" /> @Html.DisplayForModel("TestClientReferences") } |
from:http://blog.csdn.net/smartsmile2012/article/details/52936011
View Details在 Asp.NET MVC 中使用 SignalR 实现推送功能
一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息。 可访问其官方网站:https://github.com/SignalR/ 获取更多资讯。 二,实现机制 SignalR 的实现机制与 .NET WCF 或 Remoting 是相似的,都是使用远程代理来实现。在具体使用上,有两种不同目的的接口:PersistentConnection 和 Hubs,其中 PersistentConnection 是实现了长时间的 Javascript 轮询(类似于 Comet),Hub 是用来解决实时信息交换问题,它是利用 Javascript 动态载入执行方法实现的。SignalR 将整个连接,信息交换过程封装得非常漂亮,客户端与服务器端全部使用 JSON 来交换数据。 下面就 Hubs 接口的使用来讲讲整个流程: 1,在服务器端定义对应的 hub class; 2,在客户端定义 hub class 所对应的 proxy 类; 3,在客户端与服务器端建立连接(connection); 4,然后客户端就可以调用 proxy 对象的方法来调用服务器端的方法,也就是发送 request 给服务器端; 5,服务器端接收到 request 之后,可以针对某个/组客户端或所有客户端(广播)发送消息。 三,Hub 示例教程 1,工具准备 SignalR 运行在 .NET 4.5 平台上,所以需要安装 .NET 4.5。为了方便演示,本示例使用 ASP.NET MVC 在 Win 7 系统来实现。这需要安装 ASP.NET MVC 3 或 ASP.NET MVC 4。 2,建立工程 打开 VS2010/VS2012 新建名为 SignalRTutorial 的 ASP.NET MVC 3 Web Application 工程,选择 Internet Application 模板, Razor […]
View DetailsSignalR
ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。 ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信。什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及调用方法,当然这是实时操作的。 WebSockets是HTML5提供的新的API,可以在Web网页与服务器端间建立Socket连接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。 SignalR当然也提供了非常简单易用的高阶API,使服务器端可以单个或批量调用客户端上的JavaScript函数,并且非常 方便地进行连接管理,例如客户端连接到服务器端,或断开连接,客户端分组,以及客户端授权,使用SignalR都非常 容易实现。 SignalR 将与客户端进行实时通信带给了ASP .NET 。当然这样既好用,而且也有足够的扩展性。以前用户需要刷新页面或使用Ajax轮询才能实现的实时显示数据,现在只要使用SignalR,就可以简单实现了。 最重要的是您无需重新建立项目,使用现有ASP .NET项目即可无缝使用SignalR。
View DetailsWeb API 入门指南 – 闲话安全
Web API入门指南有些朋友回复问了些安全方面的问题,安全方面可以写的东西实在太多了,这里尽量围绕着Web API的安全性来展开,介绍一些安全的基本概念,常见安全隐患、相关的防御技巧以及Web API提供的安全机制。 目录 Web API 安全概览 安全隐患 1. 注入(Injection) 2. 无效认证和Session管理方式(Broken Authentication and Session Management) 3. 跨站脚本(Cross-Site Scripting (XSS)) 4. 直接引用非安全对象(Insecure Direct Object References) 5. 错误的安全配置(Security Misconfiguration) 6. 暴露敏感数据(Sensitive Data Exposure) 7. 功能级权限控制缺失(Missing Function Level Access Control) 8. 伪造跨站请求(Cross-Site Request Forgery) 9. 使用已知安全隐患组件(Using Components with Known Vulnerabilities) 10. 未验证跳转(Unvalidated Redirects and Forwards) Web API安全机制 认证与授权(Authentication and Authorization) 伪造跨站请求(Cross-Site Request Forgery Attacks) 安全链接(SSL) 跨域请求(Cross-Origin Requests) Web API 安全概览 先引用下wikipedia信息安全的定义:即保护信息免受未经授权的进入、使用、披露、破坏、修改、检视、记录及销毁,从而保证数据的机密性(Confidentiality)、完整性(Integrity)和可靠性(Availability)。 机密性和完整性都很好理解,可靠性作为信息安全的一个重要原则这里特别解释一下,即访问信息的时候保证可以访问的到,有一种攻击方式叫DOS/DDOS,即拒绝服务攻击,专门破坏网站的可用性。 Information security, sometimes shortened to InfoSec, is the practice of defending information from unauthorized access, use, disclosure, disruption, modification, perusal, […]
View DetailsWeb API 强势入门指南
Web API是一个比较宽泛的概念。这里我们提到Web API特指ASP.NET Web API。 这篇文章中我们主要介绍Web API的主要功能以及与其他同类型框架的对比,最后通过一些相对复杂的实例展示如何通过Web API构建http服务,同时也展示了Visual Studio构建.net项目的各种强大。 目录 什么是 Web API 为什么要用 Web API 功能简介 Web API vs MVC Web API vs WCF Web API 实战 (Web API + MongoDB + knockoutjs) 涉及技术 服务URI Pattern 准备工作 代码实现 什么是 Web API 官方定义如下,强调两个关键点,即可以对接各种客户端(浏览器,移动设备),构建http服务的框架。 ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework. Web API在ASP.NET完整框架中地位如下图,与SignalR一起同为构建Service的框架。Web API负责构建http常规服务,而SignalR主要负责的是构建实时服务,例如股票,聊天室,在线游戏等实时性要求比较高的服务。 为什么要用 Web API Web API最重要的是可以构建面向各种客户端的服务。另外与WCF REST […]
View DetailsASP.NET Web API教程(六) 安全与身份认证
在实际的项目应用中,很多时候都需要保证数据的安全和可靠,如何来保证数据的安全呢?做法有很多,最常见的就是进行身份验证。验证通过,根据验证过的身份给与对应访问权限。同在Web Api中如何实现身份认证呢?接下来的内容就详细的分享 Web API身份认证。 首先扩展自定义身份验证 添加类 CustomAuthorizeAttribute.cs 该类继承自System.Web.Http.AuthorizeAttribute(身份认证类)通过重写其身份认证核心方法来达到 web API 身份认证的效果。 完整代码: public class CustomAuthorizeAttribute : System.Web.Http.AuthorizeAttribute { public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) { //判断用户是否登录 if(!HttpContext.Current.User.Identity.IsAuthenticated) HandleUnauthorizedRequest(actionContext); } protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext) { var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized); challengeMessage.Headers.Add("WWW-Authenticate", "Basic"); throw new System.Web.Http.HttpResponseException(challengeMessage); } } 增加身份认证(必须登录后才能进行查询等操作)在Controller上加上属性,可以直接通过VS快捷键感应出来 完整代码 PS:写在controller类上是表示这个controller的每个action都受身份认证,如果想为某一个action制定 可以直接写在action上,就不要写在类上了。 接下来编写登录方法 public ActionResult Login() { return View(); } [HttpPost] public ActionResult Login(FormCollection fol) { ///此处为了演示简化登录过程 ///可以在此处扩展验证用户名或者密码是否正确 System.Web.Security.FormsAuthentication.SetAuthCookie(fol["username"], false); return Redirect("/HTMLPage5.htm"); } 有了后台的方法,就剩下最后的前段页面了 通过在Login的方法中右键可以快速生成页面(vs给我们带来的提高效率的工具,就不多做介绍了) 在生成的Login.cshtml中编写以下登录代码 @using (Html.BeginForm()) { <fieldset> <label>账号:</label><input type="text" name="username" /><br /> <label>密码:</label><input type="text" name="password" /><br /> <input type="submit" value="登录" /> </fieldset> } 这个时候还需要有两个小地方做配置. 第一个就是web.config 配置form认证 <authentication mode="Forms"> <forms loginUrl="~/home/Login" timeout="2880" /> </authentication> 第二个就是修改HTMLPage5.html的js(HTMLPage5.html可以直接复制HTMLPage4.html) 将这段获取数据的代码修改为带验证身份进行跳转的 原JS $.get('/api/userInfo', function (data) { // 从API中 // 得到返回的数据,更新 Knockout 模型并且绑定到页面UI模板中 viewModel.userinfos(data); }); 修改后的js $.ajax({ url: '/api/userinfo', type: 'GET', contentType: 'application/json; charset=utf-8', statusCode: { 200 /*Created*/: function (data) { viewModel.userinfos(data) }, 401: function (jqXHR, textStatus, errorThrown) { window.location.href = '/home/login'; } } }); Ok 到此,代码就已近编写完成了,来进行测试 测试第一步直接访问 /api/userinfo […]
View Detailsless
Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充。Less 可以运行在 Node 或浏览器端。 CSS(层叠样式表)是一门历史悠久的标记性语言,同 HTML 一道,被广泛应用于万维网(World Wide Web)中。HTML 主要负责文档结构的定义,CSS 负责文档表现形式或样式的定义。 作为一门标记性语言,CSS 的语法相对简单,对使用者的要求较低,但同时也带来一些问题:CSS 需要书写大量看似没有逻辑的代码,不方便维护及扩展,不利于复用,尤其对于非前端开发工程师来讲,往往会因为缺少 CSS 编写经验而很难写出组织良好且易于维护的 CSS 代码,造成这些困难的很大原因源于 CSS 是一门非程序式语言,没有变量、函数、SCOPE(作用域)等概念。LESS 为 Web 开发者带来了福音,它在 CSS 的语法基础之上,引入了变量,Mixin(混入),运算以及函数等功能,大大简化了 CSS 的编写,并且降低了 CSS 的维护成本,就像它的名称所说的那样,LESS 可以让我们用更少的代码做更多的事情。 LESS 原理及使用方式 本质上,LESS 包含一套自定义的语法及一个解析器,用户根据这些语法定义自己的样式规则,这些规则最终会通过解析器,编译生成对应的 CSS 文件。LESS 并没有裁剪 CSS 原有的特性,更不是用来取代 CSS 的,而是在现有 CSS 语法的基础上,为 CSS 加入程序式语言的特性。 客户端 我们可以直接在客户端使用 .less(LESS 源文件),只需要从http://lesscss.org下载 less.js 文件,然后在我们需要引入 LESS 源文件的 HTML 中加入如下代码: <link rel="stylesheet/less" type="text/css" href="styles.less"> LESS 源文件的引入方式与标准 CSS 文件引入方式一样: <link rel="stylesheet/less" type="text/css" href="styles.less"> 需要注意的是:在引入 .less 文件时,rel 属性要设置为“stylesheet/less”。还有更重要的一点需要注意的是:LESS 源文件一定要在 less.js 引入之前引入,这样才能保证 LESS 源文件正确编译解析。 服务器端 LESS 在服务器端的使用主要是借助于 LESS 的编译器,将 […]
View Details[MYSQL]时间毫秒数转换
[MYSQL]时间毫秒数转换 java中常用bigint字段保存时间,通常将时间保存为一大串数字,每次取出需要在程序里转换,有时候程序里不方便,可以使用MYSQL自带的函数FROM_UNIXTIME(unix_timestamp,format)。 举例: 1 select FROM_UNIXTIME(1364176514656/1000,’%Y-%m-%d %h:%i:%s') as date ; 结果为: 2013-03-25 09:55:15 FROM_UNIXTIME(unix_timestamp,format) 其中unix_timestamp为字段值/1000. format可以使用的值为: %M 月名字(January……December) %W 星期名字(Sunday……Saturday) %D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。) %Y 年, 数字, 4 位 %y 年, 数字, 2 位 %a 缩写的星期名字(Sun……Sat) %d 月份中的天数, 数字(00……31) %e 月份中的天数, 数字(0……31) %m 月, 数字(01……12) %c 月, 数字(1……12) %b 缩写的月份名字(Jan……Dec) %j 一年中的天数(001……366) %H 小时(00……23) %k 小时(0……23) %h 小时(01……12) %I 小时(01……12) %l 小时(1……12) %i 分钟, 数字(00……59) %r 时间,12 小时(hh:mm:ss [AP]M) %T 时间,24 小时(hh:mm:ss) %S 秒(00……59) %s 秒(00……59) %p AM或PM %w 一个星期中的天数(0=Sunday ……6=Saturday ) %U 星期(0……52), 这里星期天是星期的第一天 %u […]
View Details