CentOS7安装PPTP服务器
1、安装PPTP
1 |
yum install pptpd ppp |
2、配置文件
1 2 |
#修改dns信息 vim /etc/ppp/options.pptpd |
将它更改为你的dns服务地址(此处为百度和谷歌的dns)
1 2 |
ms-dns 180.76.76.76 ms-dns 8.8.8.8 |
3、vpn 账户密码
1 |
vim /etc/ppp/chap-secrets |
设置 VPN账号 + 服务类型 + VPN密码 + IP
1 2 3 4 |
# Secrets for authentication using CHAP # client server secret IP addresses 123 pptpd 012345 * 456 * 123456 * |
账户123密码012345 4、设置最大传输单元
1 2 |
vim /etc/ppp/ip-up 在命令符 [ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local “$@” 后面添加 ifconfig ppp0 mtu 1472 |
5、配置pptp配置文件
1 2 3 4 5 |
vim /etc/pptpd.conf localip 192.168.0.1 remoteip 192.168.1.100-110 localip ---本机ip地址 remoteip ---分配给客户端的地址,一般是内网网段地址 |
6、打开内核的ip 转发功能
1 2 3 |
vim /etc/sysctl.conf 编辑配置文件,添加 net.ipv4.ip_forward = 1 的配置,保存后退出。 运行 sysctl -p 使修改后的参数生效。 |
7、设置开机启动
1 2 3 4 5 |
#重启PPTP服务 systemctl restart pptpd #配置开机自启 systemctl enable pptpd.service |
8、打开防火墙
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
开启47及1723端口: firewall-cmd --zone=public --add-port=47/tcp --permanent firewall-cmd --zone=public --add-port=1723/tcp --permanent 允许防火墙伪装IP: firewall-cmd --zone=public --add-masquerade 允许gre协议: firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p gre -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p gre -j ACCEPT 设置规则允许数据包由eth0和ppp+接口中进出 firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i ppp+ -o eth0 -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i eth0 -o ppp+ -j ACCEPT 设置转发规则,从源地址发出的所有包都进行伪装,改变地址,由eth0发出:(192.168.0.0内网地址,子网地址前两位) firewall-cmd --permanent --direct --passthrough ipv4 -t nat -I POSTROUTING -o eth0 -j MASQUERADE -s 192.168.0.0/24 重启服务器: firewall-cmd --reload systemctl restart pptpd |
9、日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
1、上线日志 vim /etc/ppp/ip-up 在[ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local "$@" 后加上 echo "$PEERNAME 分配IP: $5 登录IP: $6 登录时间: `date -d today +%F_%T`" >> /var/log/pptpd.log 2、下线日志 vim /etc/ppp/ip-down 在/etc/sysconfig/network-scripts/ifdown-post --realdevice ${REALDEVICE} \ ifcfg-${LOGDEVICE} 后加上 echo "$PEERNAME 下线IP: $6 下线时间: `date -d today +%F_%T`" >> /var/log/pptpd.log |
from:https://blog.csdn.net/h18733517027/article/details/94435182
View DetailsC#中TripleDES对应Java中的DESede即大家说的3DES,附C#及Java加解密结果一致的控制台程序例子
直接上代码了。 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 DetailswebAPI 使用注解非必须参数拦截问题
使用注解可以更方便对参数进行验证,但是也会存在非必须参数如: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 Detailsaxios基础用法
概述: 1.axios:一个基于Promise用于浏览器和nodejs的HTTP客户端。本质是对ajax的封装。 特征: 从浏览器中创建XMLHttpRequest 从node.js发出http请求 支持Promise API 拦截请求和响应 转换请求和响应数据 取消请求 自动转换JSON数据 客户端支持防止CSRF/XSRF 2.安装 npm install axios import axios from "axios" 3.API 1 axios(config)
1 2 3 4 5 6 7 8 |
eg: axios({ method:"post", url:"/user", data:{ firstName:"nanhua", lastName:"qiushui" } }); |
2.axios(url,config) //默认为get请求 3.请求方法别名
1 2 3 4 5 6 7 |
axios.request(config) axios.get(url,config) axios.post(url,data,config) axios.delete(url,config) axios.head(url,config) axios.put(url,data,config) axios.patch(url,data,config) |
4.并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
自定义配置创建axios实例 var instance = axios.create({ baseURL:"https://some-domain.com/api/", timeout:1000, headers:{"X-Custom-Header":"foobar"} }) 自定义实例默认值 //创建实例时设置 //实例创建后修改默认值(设置全局axios默认值) axios.defaults.baseURL = "https://api.example.com"; axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; 并发:axios.all(iterable) eg: axios.all([ axios.get("https://api.github.com/xxx/1"); axios.get("https://api.github.com/xxx/2"); ]).then(axios.spread(function(userResp,reposResp){ console.log("User",userResp.data); console.log("Repositories",reposResp.data); })) |
1 2 |
* 当所有的请求都完成后,会收到一个数组,它包含着响应对象,其中的顺序和请求发送的顺序相同,可以用<span class="hljs-selector-tag">axios</span><span class="hljs-selector-class">.spread</span>分割成多个单独的响应对象。 |
5.config参数
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 |
baseURL: 'https://some-domain.com/api/', //将自动加在url前面,除非url是一个绝对URL //允许在向服务器发送前,修改请求数据 //只能用在PUT\POST\PATCH //后面数组的函数必须返回一个字符串/ArrayBuffer或Stream transformRequest:[function(data){ //对data进行任意转换处理 return data; }], //在传递给then/catch之前,允许修改响应数据 transformResponse: [function (data) { return data; }], //即将被发送的自定义请求头 headers:{ 'X-Requested-With': 'XMLHttpRequest' }, //即将与请求一起发送的URL参数 params:{ ID: 12345 }, //负责params序列化的函数 paramsSerializer:function(params){ return Qs.stringify(params,{arrayFormat: "brackets"}); }, //超时 timeout: 1000, //表示跨域请求时是否需要使用凭证 withCredentials: false, //允许响应内容的最大尺寸 maxContentLength: 2000, //对打重定向数目 maxRedirects:5, //是否启用长连接 httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), //代理服务器设置 proxy:{ host:"127.0.0.1", port: 9000, auth:{ username:"nanhuaqiushui", password:"Huawei@123" } } |
6.响应结构
1 2 3 4 5 6 7 |
{ data:{}, status:200, statusText:"OK", headers:{}, //服务器响应的头 config:{} //为请求提供的配置信息 } |
7.拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//请求拦截器 axios.interceptors.request.use(function(config){ //发送请求之前做些什么 return config; },function(error){ //请求错误之后做些什么 return Promise.reject(error); }) //响应添加拦截器 axios.interceptors.response.use(function(config){ //发送请求之前做些什么 return config; },function(error){ //请求错误之后做些什么 return Promise.reject(error); }) //移除拦截器 var myInterceptor = axios.interceptors.request.use(function(){ ... }) axios.interceptors.request.eject(myInterceptor); |
新兴实践
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 |
const service = axios.create({ baseURL: process.env.BASE_API, timeout: 100000 }) // 请求拦截器 service.interceptors.request.use( config => { config.headers['Content-Type'] = 'application/json' if (store.getters.token) { // 让每个请求携带token config.headers['Authorization'] = store.getters.token } return config }, error => { Toast.failed('网络异常,请检查网络连接') console.log(error) // for debug return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response => { const res = response.data if (res.code && res.code !== 200) { Toast.failed(res.message) } return response }, error => { Toast.failed('网络异常,请检查网络连接') return Promise.reject(error) } ) export default service |
from:https://www.cnblogs.com/nanhuaqiushui/p/10514122.html
View Detailsvue中$emit与$on和BUS
bus: //vue原型链挂载总线 Vue.prototype.bus = new Vue(); //子组件发送数据 this.bus.$emit("change",data); //子组件接收数据 this.bus.$on("change",function(data){ }) vue中$emit与$on var Event = new Vue(); 相当于又new了一个vue实例,Event中含有vue的全部方法; Event.$emit('msg',this.msg); 发送数据,第一个参数是发送数据的名称,接收时还用这个名字接收,第二个参数是这个数据现在的位置; Event.$on('msg',function(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 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 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>孙三峰--博客园</title> <script type="text/javascript" src="js/vue2.0.3.js" ></script> <script type="text/javascript"> //准备一个空的实例对象 var Event = new Vue(); var A={ template:` <div style="border: 1px solid red; margin-bottom: 10px; width: 300px;"> <h4>A组件</h4> <p>{{a}}</p> <input type="button" value="把A数据给C" @click="send" /> </div> `, data(){ return { a:'我是A里面的数据' } }, methods:{ send(){ //A发送数据 Event.$emit('a-msg',this.a); } } }; var B={ template:` <div style="border: 1px solid green; margin-bottom: 10px; width: 300px;"> <h4>B组件</h4> <p>{{b}}</p> <input type="button" value="把B数据给C" @click="send" /> </div> `, data(){ return { b:'我是B里面的数据' } }, methods:{ send(){ Event.$emit('b-msg',this.b); } } }; var C={ template:` <div style="border: 1px dotted green; margin-bottom: 10px;width: 300px;"> <h4>我是C组件,我在坐等接收数据</h4> <p>{{a}}</p> <p>{{b}}</p> </div> `, data(){ return{ a:'', b:'' } }, mounted(){ //两种接收的方式 var _this = this; Event.$on('a-msg',function(a){ _this.a=a; }); Event.$on('b-msg',function(b){ this.b = b; }.bind(this)) } }; window.onload=function(){ new Vue({ el:'#box', data:{ }, components:{ 'com-a':A, 'com-b':B, 'com-c':C } }) } </script> </head> <body> <div id="box"> <com-a></com-a> <com-b></com-b> <com-c></com-c> </div> </body> </html> |
效果图: from:https://www.cnblogs.com/wang-sai-sai/p/11158770.html
View DetailsPHP:cURL error 60: SSL certificate unable to get local issuer certificate
导致该问题的原因在于没有配置curl.cainfo,该配置位于php.ini中。 解决方案: 1)下载cacert.pem https://curl.haxx.se/ca/cacert.pem 2)配置php.ini [curl] ; A default value for the CURLOPT_CAINFO option. This is required to be an ; absolute path. curl.cainfo = 【你的绝对路径】 ———————————————— 版权声明:本文为CSDN博主「loophome」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/loophome/java/article/details/83112364
View Detailsasp.net获取IP
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
WEBAPI 返回一个html页面
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实现简单的文件下载与上传。首先创建一个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各种文件对应的MIMEType
由上可见,MIME_MapTable是所有文件的后缀名所对应的MIME类型的一个String数组: Java代码 final String[][] MIME_MapTable={ //{后缀名,MIME类型} {".3gp", "video/3gpp"}, {".apk", "application/vnd.android.package-archive"}, {".asf", "video/x-ms-asf"}, {".avi", "video/x-msvideo"}, {".bin", "application/octet-stream"}, {".bmp", "image/bmp"}, {".c", "text/plain"}, {".class", "application/octet-stream"}, {".conf", "text/plain"}, {".cpp", "text/plain"}, {".doc", "application/msword"}, {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, {".xls", "application/vnd.ms-excel"}, {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, {".exe", "application/octet-stream"}, {".gif", "image/gif"}, {".gtar", "application/x-gtar"}, {".gz", "application/x-gzip"}, {".h", "text/plain"}, {".htm", "text/html"}, {".html", "text/html"}, {".jar", "application/java-archive"}, {".java", "text/plain"}, {".jpeg", "image/jpeg"}, {".jpg", "image/jpeg"}, {".js", "application/x-javascript"}, {".log", "text/plain"}, {".m3u", "audio/x-mpegurl"}, {".m4a", "audio/mp4a-latm"}, {".m4b", "audio/mp4a-latm"}, {".m4p", "audio/mp4a-latm"}, {".m4u", "video/vnd.mpegurl"}, {".m4v", "video/x-m4v"}, {".mov", "video/quicktime"}, {".mp2", "audio/x-mpeg"}, {".mp3", "audio/x-mpeg"}, {".mp4", "video/mp4"}, {".mpc", "application/vnd.mpohun.certificate"}, {".mpe", "video/mpeg"}, {".mpeg", "video/mpeg"}, {".mpg", "video/mpeg"}, {".mpg4", "video/mp4"}, {".mpga", "audio/mpeg"}, {".msg", "application/vnd.ms-outlook"}, {".ogg", "audio/ogg"}, {".pdf", "application/pdf"}, {".png", "image/png"}, {".pps", "application/vnd.ms-powerpoint"}, {".ppt", "application/vnd.ms-powerpoint"}, {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, {".prop", "text/plain"}, {".rc", "text/plain"}, {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"}, {".sh", "text/plain"}, {".tar", "application/x-tar"}, {".tgz", "application/x-compressed"}, {".txt", "text/plain"}, {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"}, {".wmv", "audio/x-ms-wmv"}, {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"}, {".z", "application/x-compress"}, {".zip", "application/x-zip-compressed"}, {"", "*/*"} }; ———————————————— 版权声明:本文为CSDN博主「零下忆度」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/sinat_30474567/java/article/details/53411146
View Details