HttpWebRequest POST请求webapi:如果参数是简单类型,比如字符串(注意,拼接的字符串要HttpUtility.UrlEncode才行,否则服务端会丢失特殊字符&后面的数据) 要点:如下代码统一设置为:ContentType = "application/x-www-form-urlencoded"; 服务端代码1:URL格式为 POSTapi/Values public string Post([FromBody] string value) 则客户端Post的数据:拼接的字符串必须以 =开头,否则服务端无法取得value。例如:=rfwreewr2332322232 或者 {":value} 服务端代码2:URL格式为 POST api/Values?value={value} public string Post(string value) 则客户端Post的数据:需要url里拼接出KeyValue这样的数据 服务端代码3:URL格式为 POST api/Values public string Post() 则客户端Post的数据:无要求。例如:key=rfwreewr2332322232。 服务端:可以用HttpContext.Current.Request.InputStream或者HttpContext.Current.Request.Form[0]都可以获取 如果post的参数类型比较复杂,则需要自定义类 要点:如下代码统一设置为:ContentType = "application/json"; 服务端代码1:URL格式为 POST api/Values public string Post([FromBody] Model value)或者 public string Post(Model value) 则客户端Post的数据:{\"id\":\"test1\",\"name\":\"value\"}。服务端会自动映射到对象。 提交代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
HttpWebRequest wReq = (HttpWebRequest)WebRequest.Create("http://localhost:37831/api/Values"); wReq.Method = "Post"; //wReq.ContentType = "application/json"; //wReq.ContentType = "application/x-www-form-urlencoded"; wReq.ContentType = "application/json"; //byte[] data = Encoding.Default.GetBytes(HttpUtility.UrlEncode("key=rfwreewr2332322232&261=3&261=4")); byte[] data = Encoding.Default.GetBytes("{\"id\":\"test1\",\"name\":\"value\"}"); wReq.ContentLength = data.Length; Stream reqStream = wReq.GetRequestStream(); reqStream.Write(data, 0, data.Length); reqStream.Close(); using (StreamReader sr = new StreamReader(wReq.GetResponse().GetResponseStream())) { string result = sr.ReadToEnd(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// POST api/values //public string Post() //{ // FileInfo fi = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log.txt"); // StreamWriter sw = fi.CreateText(); // StreamReader sr = new StreamReader(HttpContext.Current.Request.InputStream); // sw.WriteLine("1:" + sr.ReadToEnd()+"--"+ HttpContext.Current.Request.Form[0]); // sw.Flush(); // sw.Close(); // return "{\"test\":\"1\"}"; //} // POST api/values public HttpResponseMessage PostStudent(Student student) { FileInfo fi = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log.txt"); StreamWriter sw = fi.AppendText(); sw.WriteLine("2:" + student.id); sw.Flush(); sw.Close(); HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent("{\"test\":\"2\"}", Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } |
这篇文章里有的方法也不错:http://www.cnblogs.com/rohelm/p/3207430.html from:http://blog.csdn.net/wyqlxy/article/details/49303345
View Details
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一,简介 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 DetailsASP.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 安全概览 安全隐患 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特指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 Details在实际的项目应用中,很多时候都需要保证数据的安全和可靠,如何来保证数据的安全呢?做法有很多,最常见的就是进行身份验证。验证通过,根据验证过的身份给与对应访问权限。同在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 DetailsSpring Framework 5.0 GA 稳定版已正式发布。 经过一年多的里程碑版和 RC 版,以及将近两年的开发,Spring Framework 5.0 GA 稳定版现已正式发布。可从 repo.spring.io 和 Maven Central 获得。 这个全新一代的框架带来了以下新特性: 支持 JDK 9 和 Java EE 8 级别的 API(如 Servlet 4.0) 与 Reactor 3.1, JUnit 5, 和 Kotlin 语言的全面集成 带来了许多函数式 API 变体 (functional API variants) 响应式堆栈 Web 框架 —— Spring WebFlux 此外,值得注意的是,整个 Spring Framework 5.0 代码库运行于 Java 8 之上。因此 Spring Framework 5.0 对环境的最低要求是 Java 8。 可以看到,Spring Framework 5.0 的亮点是响应式编程,这是一个重要的范式转变。随着响应式编程越来越受欢迎,我们可以期待越来越多的技术将实现响应式解决方案。 相关链接: Spring Framework 5.0 中的新功能 迁移到 Spring Framework 5.0 官方的 Spring Framework 5 FAQ 最新的参考文档 更多内容请参阅发布主页和详细更新说明。 Maven
1 2 3 4 5 6 7 |
<span class="hljs-tag"><<span class="hljs-name">dependencies</span>></span> <span class="hljs-tag"><<span class="hljs-name">dependency</span>></span> <span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span> <span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-context<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span> <span class="hljs-tag"><<span class="hljs-name">version</span>></span>5.0.0.RELEASE<span class="hljs-tag"></<span class="hljs-name">version</span>></span> <span class="hljs-tag"></<span class="hljs-name">dependency</span>></span> <span class="hljs-tag"></<span class="hljs-name">dependencies</span>></span> |
Gradle
1 2 3 |
dependencies { compile <span class="hljs-string">'org.springframework:spring-context:5.0.0.RELEASE'</span> } |
下载地址: http://projects.spring.io/spring-framework/ Source code (zip) Source code (tar.gz) 相关链接 […]
View DetailsPHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个PHPFastCGI管理器,对于PHP 5.3.3之前的php来说,是一个补丁包[1] ,旨在将FastCGI进程管理整合进PHP包中。如果你使用的是PHP5.3.3之前的PHP的话,就必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。 相对Spawn-FCGI,PHP-FPM在CPU和内存方面的控制都更胜一筹,而且前者很容易崩溃,必须用crontab进行监控,而PHP-FPM则没有这种烦恼。
View Details多少年来,许多的编程语言和工具都包含对正则表达式的支持,.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类,而且它们也都与未来的Perl 5中的规则表达式兼容。 此外,regexp类还能够完成一些其他的功能,例如从右至左的结合模式和表达式的编辑等。 在这篇文章中,我将简要地介绍System.Text.RegularExPRession中的类和方法、一些字符串匹配和替换的例子以及组结构的详细情况,最后,还会介绍一些你可能会用到的常见的表达式。 应该掌握的基础知识 规则表达式的知识可能是不少编程人员“常学常忘”的知识之一。在这篇文章中,我们将假定你已经掌握了规则表达式的用法,尤其是Perl 5中表达式的用法。.NET的regexp类是Perl 5中表达式的一个超集,因此,从理论上说它将作为一个很好的起点。我们还假设你具有了C#的语法和.NET架构的基本知识。 如果你没有规则表达式方面的知识,我建议你从Perl 5的语法着手开始学习。在规则表达式方面的权威书籍是由杰弗里·弗雷德尔编写的《掌握表达式》一书,对于希望深刻理解表达式的读者,我们强烈建议阅读这本书。 RegularExpression组合体 regexp规则类包含在System.Text.RegularExpressions.dll文件中,在对应用软件进行编译时你必须引用这个文件,例如: csc r:System.Text.RegularExpressions.dll foo.cs 命令将创建foo.exe文件,它就引用了System.Text.RegularExpressions文件。 名字空间简介 在名字空间中仅仅包含着6个类和一个定义,它们是: Capture: 包含一次匹配的结果; CaptureCollection: Capture的序列; Group: 一次组记录的结果,由Capture继承而来; Match: 一次表达式的匹配结果,由Group继承而来; MatchCollection: Match的一个序列; MatchEvaluator: 执行替换操作时使用的代理; Regex: 编译后的表达式的实例。 Regex类中还包含一些静态的方法: Escape: 对字符串中的regex中的转义符进行转义; IsMatch: 如果表达式在字符串中匹配,该方法返回一个布尔值; Match: 返回Match的实例; Matches: 返回一系列的Match的方法; Replace: 用替换字符串替换匹配的表达式; Split: 返回一系列由表达式决定的字符串; Unescape:不对字符串中的转义字符转义。 简单匹配 我们首先从使用Regex、Match类的简单表达式开始学习。 Match m = Regex.Match("abracadabra", "(a|b|r)+"); 我们现在有了一个可以用于测试的Match类的实例,例如:if (m.Success)… 如果想使用匹配的字符串,可以把它转换成一个字符串: Console.WriteLine("Match="+m.ToString()); 这个例子可以得到如下的输出: Match=abra。这就是匹配的字符串了。 字符串的替换 简单字符串的替换非常直观。例如下面的语句: string s = Regex.Replace("abracadabra", "abra", "zzzz"); 它返回字符串zzzzcadzzzz,所有匹配的字符串都被替换成了zzzzz。 现在我们来看一个比较复杂的字符串替换的例子: string s = Regex.Replace(" abra ", @"^\s*(.*?)\s*$", "$1"); 这个语句返回字符串abra,其前导和后缀的空格都去掉了。 上面的模式对于删除任意字符串中的前导和后续空格都非常有用。在C#中,我们还经常使用字母字符串,在一个字母字符串中,编译程序不把字符“ \” 作为转义字符处理。在使用字符“\”指定转义字符时,@"…"是非常有用的。另外值得一提的是$1在字符串替换方面的使用,它表明替换字符串只能包含被替换的字符串。 匹配引擎的细节 现在,我们通过一个组结构来理解一个稍微复杂的例子。看下面的例子: string text = "abracadabra1abracadabra2abracadabra3"; string […]
View Details