直接上代码了。 Java控制台代码: package Test; import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.IvParameterSpec; import org.apache.commons.codec.binary.Base64; public class Test { private static final String encoding = "UTF-8"; public static void main(String[] args) { try { String text = "20200121";// 明文 String key = "Tt3rLPrDIVIhXqAz";// 长度控制为16,作为3DES加密用的key String encryptStr = EncryptData(text, key);// 3DES加密结果 System.out.println("明文:" + text); System.out.println("密钥:" + key); System.out.println("密文:" + encryptStr); System.out.println("解密:" + DecryptData(encryptStr, key)); } catch (Exception e) { e.printStackTrace(); } } /** * DESede加密,key长度为16 * * @param plainText 明文 * @param key 密钥 * @return DESede加密结果 * […]
View Details使用注解可以更方便对参数进行验证,但是也会存在非必须参数如:https://aaa.com?id=1&name=&age=;或https://aaa.com?id=1&name&age的请求。这时ModelState.IsValid过滤器将会拦截请求提示"值是必需的。"或"有一个值是必需的,但请求中不存在该值。"异常。 若接口使用model接收参数,可将值类型参数改为可空类型解决此问题;如:
1 |
int?id |
若接口不使用model接收参数,暂无没有找到解决方案; 经过调试可以使用一种笨拙的取巧方案解决:在过滤器.ModelState.IsValid==false内部对值的错误内容进行排除
1 2 3 4 |
if (Msg != "有一个值是必需的,但请求中不存在该值。" && Msg != "值是必需的。") { return; } |
from:https://blog.csdn.net/niuc321/article/details/88694793
View Details
1 2 3 4 5 6 7 8 9 10 11 12 |
/// <summary> /// get ip /// </summary> /// <returns></returns> public static string GetIp() { var context = HttpContext.Current; return context.Request.ServerVariables["HTTP_X_REAL_IP"] ?? context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? context.Request.ServerVariables["REMOTE_ADDR"] ?? "unknow"; } |
View Details
public HttpResponseMessage getHtml() { string uri = "http://docs.google.com/gview?embedded=true&url=www.pdf995.com/samples/pdf.pdf"; WebClient wc = new WebClient(); Stream resStream = wc.OpenRead(uri); StreamReader sr = new StreamReader(resStream, System.Text.Encoding.Default); string ContentHtml = sr.ReadToEnd(); var response = new HttpResponseMessage(); response.Content = new StringContent(ContentHtml); response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); return response; } ———————————————— 版权声明:本文为CSDN博主「小咪蜂」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/xiaomifengmaidi1/java/article/details/84665109
View DetailsASP.NET Web API实现简单的文件下载与上传。首先创建一个ASP.NET Web API项目,然后在项目下创建FileRoot目录并在该目录下创建ReportTemplate.xlsx文件,用于下面示例的使用。 1、文件下载 示例:实现报表模板文件下载功能。 1.1 后端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/// <summary> /// 下载文件 /// </summary> [HttpGet] public HttpResponseMessage DownloadFile() { string fileName = "报表模板.xlsx"; string filePath = HttpContext.Current.Server.MapPath("~/") + "FileRoot\\" + "ReportTemplate.xlsx"; FileStream stream = new FileStream(filePath, FileMode.Open); HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); response.Content = new StreamContent(stream); response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = HttpUtility.UrlEncode(fileName) }; response.Headers.Add("Access-Control-Expose-Headers", "FileName"); response.Headers.Add("FileName", HttpUtility.UrlEncode(fileName)); return response; } |
1.2 前端代码
1 |
<a href="http://localhost:51170/api/File/DownloadFile">下载模板</a> |
2、文件上传 示例:实现上传报表文件功能。 2.1 后端代码
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 |
/// <summary> /// 上传文件 /// </summary> [HttpPost] public HttpResponseMessage UploadFile() { try { //获取参数信息 HttpContextBase context = (HttpContextBase)Request.Properties["MS_HttpContext"]; HttpRequestBase request = context.Request; //定义传统request对象 string monthly = request.Form["Monthly"]; //获取请求参数:月度 string reportName = request.Form["ReportName"]; //获取请求参数:报表名称 //保存文件 string fileName = String.Format("{0}_{1}.xlsx", monthly, reportName); string filePath = HttpContext.Current.Server.MapPath("~/") + "FileRoot\\" + fileName; request.Files[0].SaveAs(filePath); //返回结果 var result = new HttpResponseMessage { Content = new StringContent("上传成功", Encoding.GetEncoding("UTF-8"), "application/json") }; return result; } catch (Exception ex) { throw ex; }; } |
2.2 前端代码
1 2 3 4 5 6 |
<form action='http://localhost:51170/api/File/UploadFile' method="post" enctype="multipart/form-data"> 报表月份:<input type="text" name="Monthly" value="2018-11" /><br /> 报表名称:<input type="text" name="ReportName" value="财务报表" /><br /> 报表文件:<input type="file" name="file" /><br /> <input type="submit" value="提交" /> </form> |
from:https://blog.csdn.net/pan_junbiao/article/details/84065952
View Details介绍下使用Dapper-Extensions的基本语法 //实体类 DemoEntity entity = new DemoEntity(); //根据实体主键删除 this.Delete<DemoEntity>(entity); //根据主键ID删除 this.Delete<DemoEntity>(1); //增加 this.Insert<DemoEntity>(entity); //更新 bool result = this.Update<DemoEntity>(entity); //根据主键返回实体 entity = this.GetById<DemoEntity>(1); //返回 行数 this.Count<DemoEntity>(new { ID = 1 }); //查询所有 IEnumerable<DemoEntity> list = this.GetAll<DemoEntity>(); IList<ISort> sort = new List<ISort>(); sort.Add(new Sort { PropertyName = "ID", Ascending = false }); //条件查询 list = this.GetList<DemoEntity>(new { ID = 1, Name = "123" }, sort); //orm 拼接条件 查询 IList<IPredicate> predList = new List<IPredicate>(); predList.Add(Predicates.Field<DemoEntity>(p => p.Name, Operator.Like, "不知道%")); predList.Add(Predicates.Field<DemoEntity>(p => p.ID, Operator.Eq, 1)); IPredicateGroup predGroup = Predicates.Group(GroupOperator.And, predList.ToArray()); list […]
View Details1、前言 WebAPI主要开放数据给手机APP,Pad,其他需要得知数据的系统,或者软件应用。Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能。我上次写的《Asp.Net MVC WebAPI的创建与前台Jquery ajax后台HttpClient调用详解》这种跟明显安全性不是那么好,于是乎这个就来了 ,用户需要访问的API都必须带有票据过来,说白了就是登陆之后含有用户信息的Token。开始撸… 2、新建一个WebApi项目 在App_Start文件夹下面新建一个BaseApiController控制器,这是基础的Api控制器,后面有要验证的接口都继承这个控制器:
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 |
using LoginReqToken.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; namespace LoginReqToken.App_Start { /// <summary> /// 基础Api控制器 所有的都继承他 /// </summary> public class BaseApiController : ApiController { /// <summary> /// 构造函数赋值 /// </summary> public BaseApiController() { TokenValue = HttpContext.Current.Session[LoginID] ?? ""; HttpContext.Current.Request.Headers.Add("TokenValue", TokenValue.ToString()); } /// <summary> /// 数据库上下文 /// </summary> public WYDBContext db = WYDBContextFactory.GetDbContext(); /// <summary> /// token值 登录后赋值请求api的时候添加到header中 /// </summary> public static object TokenValue { get; set; } = ""; /// <summary> /// 登录者账号 /// </summary> public static string LoginID { get; set; } = ""; } } |
这个构造函数里主动加一个header头信息 ,因为每次访问的时候都要执行构造函数,在那边验证的时候都要从Header中取出来,计算出用户名 是否跟Session缓存的一致这样判断的 3、在建一个TokenCheckFilter.cs 继承AuthorizeAttribute重写基类的验证方式,重写HandleUnauthorizedRequest
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 |
using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Web; using System.Web.Helpers; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Security; namespace LoginReqToken.App_Start { /// <summary> /// token验证 /// </summary> public class TokenCheckFilter: AuthorizeAttribute { /// <summary> /// 重写基类的验证方式,加入自定义的Ticket验证 /// </summary> /// <param name="actionContext"></param> public override void OnAuthorization(HttpActionContext actionContext) { var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase; //获取token(请求头里面的值) var token = HttpContext.Current.Request.Headers["TokenValue"] ?? ""; //是否为空 if (!string.IsNullOrEmpty(token.ToString())) { //解密用户ticket,并校验用户名密码是否匹配 if (ValidateTicket(token.ToString())) base.IsAuthorized(actionContext); else HandleUnauthorizedRequest(actionContext); } //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证403 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); } } //校验用户名密码(对Session匹配,或数据库数据匹配) private bool ValidateTicket(string encryptToken) { //解密Ticket var strTicket = FormsAuthentication.Decrypt(encryptToken).UserData; //从Ticket里面获取用户名和密码 var index = strTicket.IndexOf("&"); string userName = strTicket.Substring(0, index); string password = strTicket.Substring(index + 1); //取得session,不通过说明用户退出,或者session已经过期 var token = HttpContext.Current.Session[userName]; if (token == null) return false; //对比session中的令牌 if (token.ToString() == encryptToken) return true; return false; } /// <summary> /// 重写HandleUnauthorizedRequest /// </summary> /// <param name="filterContext"></param> protected override void HandleUnauthorizedRequest(HttpActionContext filterContext) { base.HandleUnauthorizedRequest(filterContext); var response = filterContext.Response = filterContext.Response ?? new HttpResponseMessage(); //状态码401改为其他状态码来避免被重定向。最合理的是改为403,表示服务器拒绝。 response.StatusCode = HttpStatusCode.Forbidden; var content = new { success = false, errs = new[] { "服务端拒绝访问:你没有权限?,或者掉线了?" } }; response.Content = new StringContent(Json.Encode(content), Encoding.UTF8, "application/json"); } } } |
4、在WebApiConfig.cs配置文件里面修改一下路由加上/{action},这样就能调用到具体的哪一个了 Webapi默认是不支持Session的,所以我们需要在Global加载时候添加对Session的支持,在Global.asax里面重写Application_PostAuthorizeRequest,不然运行调用会直接异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } /// <summary> /// 重写Application_PostAuthorizeRequest /// </summary> protected void Application_PostAuthorizeRequest() { //对Session的支持,不然运行调用会直接异常 HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); } } |
5、现在来写一个登陆 新建一个控制器LoginController继承BaseApiController 里面写一个登陆的方法Login 登陆页面就直接在Home的index里面写一个简单的就行了这个控制器访问就不受限制了加上注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[AllowAnonymous] public class LoginController : BaseApiController { [HttpGet] public object Login(string uName, string uPassword) { var user = db.Users.Where(x => x.LoginID == uName && x.Password == uPassword).FirstOrDefault(); if (user==null) { return Json(new { ret = 0, data = "", msg = "用户名密码错误" }); } FormsAuthenticationTicket token = new FormsAuthenticationTicket(0, uName, DateTime.Now, DateTime.Now.AddHours(12), true, $"{uName}&{uPassword}", FormsAuthentication.FormsCookiePath); //返回登录结果、用户信息、用户验证票据信息 var _token = FormsAuthentication.Encrypt(token); //将身份信息保存在session中,验证当前请求是否是有效请求 LoginID = uName; TokenValue = _token; HttpContext.Current.Session[LoginID] = _token; return Json(new { ret = 1, data = _token, msg = "登录成功!" }); } } |
登陆页面 简单而粗暴
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 |
<br /><br /> <input type="text" name="txtLoginID" id="txtLoginID" /> <br /><br /> <input type="password" name="txtPassword" id="txtPassword" /> <br /><br /> <input type="button" id="btnSave" value="登录验证" /> <script type="text/javascript" src="~/Scripts/jquery-3.3.1.js"></script> <script type="text/javascript"> $(document).ready(function () { $("#btnSave").click(function () { $.ajax({ type: "GET", url: "/Api/Login/Login", dataType: "json", data: { "uName": $("#txtLoginID").val(), "uPassword": $("#txtPassword").val()}, success: function (data) { if (data.ret > 0) { alert(data.msg+"Token: "+data.data); } else { alert(data.msg); } }, error: function (ret) { console.log(ret); } }); }); }); </script> |
登陆这个我是写了链接数据库的自己练习可以最易更改一个固定的值 现在应该可以看到返回的Token数据了 6、现在就可以写Api 都继承BaseApiController这个控制器的方法上面需要验证的都要加上验证的注解,我是整个控制都要就直接写在类上面了,随便写一个举举例子,就比如全国省市县的查询
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 |
using LoginReqToken.App_Start; using LoginReqToken.Models; using LoginReqToken.Models.DTO; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace LoginReqToken.Controllers { /// <summary> /// 区域查询 /// </summary> [TokenCheckFilter] public class AreaOpController : BaseApiController { /// <summary> /// 获取全部区域 /// </summary> /// <returns></returns> public Result GetAllAreas() { var data = db.AddressAll.OrderBy(x => x.ID); if(data.Count()>0) { var ret = new Result() { Ret = 1, Code = "200", Msg = "获取数据成功", Data = JsonConvert.SerializeObject(data) }; return ret; } else { var ret = new Result() { Ret = 0, Code = "400", Msg = "接口失败异常", Data = "" }; return ret; } } /// <summary> /// 查询某个省市直辖市自治区下所有的信息 /// </summary> /// <param name="name">省名称(全名)</param> /// <returns></returns> public Result GetProvinceByName(string name) { var codeID = db.AddressAll.FirstOrDefault(x => x.Name == name)?.ID; if(codeID<=0) { var ret = new Result() { Ret = 1, Code = "F", Msg = "没有查到相关数据", Data = "" }; return ret; } var bb = db.AddressAll.Where(x=>x.ID>0).AsEnumerable(); var data = GetProvinceCity(bb,codeID).ToList(); if (data.Count() > 0) { var ret = new Result() { Ret = 1, Code = "200", Msg = "获取数据成功", Data = JsonConvert.SerializeObject(data) }; return ret; } else { var ret = new Result() { Ret = 0, Code = "500", Msg = "查询不到数据或者接口调用出错", Data = "" }; return ret; } } /// <summary> /// 递归获取树形数据 /// </summary> /// <param name="areasDTOs"></param> /// <param name="parentID"></param> /// <returns></returns> public IEnumerable<object> GetProvinceCity(IEnumerable<AddressAll> areasDTOs,int? parentID) { var data = areasDTOs as AddressAll[] ?? areasDTOs.ToArray(); var ret = data.Where(n => n.ParentID == parentID).Select(n => new { n.ID, n.Code, n.ParentID, n.Name, n.LevelNum, n.OrderNum, children = GetProvinceCity(data, n.ID) }); return ret; } } } |
记录一个EF随意取数据库条数信息是这么写的 var data = db.CnblogsList.OrderBy(p => Guid.NewGuid()).Take(100); 现在看效果图 没有登陆的时候是进不去的 postman上面的效果也看一下 效果都是一样的,如果登录了就可以直接访问 了 不用加参数 ,只有方法需要参数的就可以加 这里贴一个调用的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
HttpClient bb = new HttpClient(); //获取端口 HttpContent httpContent = new StringContent(""); httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); var dl = bb.GetAsync("http://localhost:63828/api/Login/login?uName=admin&uPassword=admin888").Result.Content.ReadAsStringAsync().Result; var token = JsonConvert.DeserializeObject<Result>(dl); for (var i=0;i<100;i++) { var ret = bb.GetAsync("http://localhost:63828/api/Cnblog/GetAllArtic").Result.Content.ReadAsStringAsync().Result; } |
7、总结 1)、总体思路,如果是合法的Http请求,在Http请求头中会有用户身份的票据信息,服务端会读取票据信息,并校验票据信息是否完整有效,如果满足校验要求,则进行业务数据的处理,并返回给请求发起方; 2) 如果没有票据信息,或者票据信息不是合法的,则返回“未授权的访问”异常消息给前端,由前端处理此异常。 3)、登录的时候判断用户名跟密码对不对,对了就生成用户信息的Token,Session保存一个Token,BaseApiController里面的登录名跟Token也赋值了。保存这些票据信息。 4)、当用户有权限操作页面或页面元素时,跳转到页面,并由页面Controller提交业务数据处理请求到api服务器; 如果用户没有权限访问该页面或页面元素时,则显示“未授权的访问操作”,跳转到系统异常处理页面。 5)、 api业务服务处理业务逻辑,并将结果以Json 数据返回,返回渲染后的页面给浏览器前端,并呈现业务数据到页面; 8、测试地址 http://www.yijianlan.com:8001/ ———————->先登录,用户名 test密码 […]
View Details
1 2 3 |
string str="{\"msgType\":1001,\"msgstring\":\"信息\"}";//这里是你的json带有反斜杠的 HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };//这里是去掉反斜杠再放回出去,json就只剩下双引号。 return result; |
from:https://www.cnblogs.com/taozihua/articles/8716362.html
View DetailsALTER DATABASE 数据库 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; ALTER TABLE 表 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 数据库连接字符串加上:charset=utf8mb4
View Details最近遇到一个mysql生产问题,一直报:报错误 0x80004005 Incorrect string value: '\xF0\xA0\x83\x8A2\xE4…' for column 经过排查原来数据库和表都是默认utf8编码,老司机都知道,mysql中的utf8编码有一个大坑,不是真正的utf8。当遇到特殊字符就会插入失败报下面的错误: MySql.Data.MySqlClient.MySqlException (0x80004005): Incorrect string value: '\xF0\xA0\x83\x8A2\xE4…' for column 使用环境: 1、asp.net core 2.2 2、dapper 3、mysql8 通过下面步骤完美解决: 一、首先查看当前数据库编码 1 show variables like 'character%' 最后必须要达到下面的设置: 二、更改数据库编码 1 ALTER DATABASE 数据库名称 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 三、更改所有表和列编码 先生成所有表的更改语句,这样可以批量mysql所有表和列编码为utf8mb4 1 2 3 4 5 6 7 8 9 10 SELECT CONCAT( 'ALTER TABLE ', TABLE_NAME, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;' ) FROM information_schema.TABLES WHERE TABLE_SCHEMA =’数据库名称'; 把上面查询结果导出,执行就行了。 四、更改数据库配置 数据库配置my.ini或my.cnf,你的配置可能不叫这个句子。 修改为如下配置: 1 2 3 4 5 6 7 [client] default-character-set=utf8mb4 [mysql] default-character-set=utf8mb4 [mysqld] collation-server = utf8mb4_general_ci character-set-server = utf8mb4 更改之后重启mysql 五、修改数据库连接 经过上面4步骤,以为就万事大吉了。 注意:一定要修改程序的数据库连接,不然照样报错。 如下: 1 Host=localhost;Port=3306;Database=lanhu;Uid=www.lanhusoft.com;pwd=lanhusoft;Charset=utf8mb4; 之前我们写成utf8都不行,一定要写成utf8mb4 from:https://lesg.cn/Article-53016.html
View Details