在Apache下bW博客强制访问HTTPS

HTTPS已经是大势所趋了,而国内的网络环境更需要尽早的使用HTTPS,因为运营商太流氓,像DNS劫持什么的都是家常便饭了,如果运营商的DNS劫持系统被黑,黑客利用这个系统给网站加上点什么恶意代码,那损失就更大了。下面就说下在bW下,怎样强制访问https。
如果已经开启了伪静态(使用官方的规则),那么请使用下面的.htaccess文件内容:

RewriteEngine on
RewriteBase /

# RewriteCond %{REQUEST_FILENAME} -f [OR]
# RewriteCond %{REQUEST_FILENAME} -d
# RewriteRule ^.*$ - [L]

RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

RewriteRule ^index/([0-9]+)/?$ index.php/$1/ [QSA,L]
RewriteRule ^category/([^/]+)/([0-9]+)/?$ category.php/$1/$2/ [QSA,L]
RewriteRule ^category/([^/]+)/?$ category.php/$1/ [QSA,L]
RewriteRule ^post/([^/]+)/?$ read.php/$1/ [QSA,L]
RewriteRule ^tag/([^/]+)/([0-9]+)/?$ tag.php/$1/$2/ [QSA,L]
RewriteRule ^tag/([^/]+)/?$ tag.php/$1/ [QSA,L]
RewriteRule ^page/([^/]+)/?$ page.php/$1/ [QSA,L]

如果未开启伪静态,请使用下面的内容:

RewriteEngine on
RewriteBase /
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

以上。

C# 实现的Javascript加密算法

不打算公开的,不过转念一想,反正又没人看,就发出来吧。
这是使用C#来实现的JS加密的,被加密的JS文件,代码需要写的规范,不能少了分号(;)等js中可能会被忽略的符号。
下面是完整代码,自己看吧

    public class JavascriptEncoder
    {
        public static string ENCODE_BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
        public bool isDebug = false;

        public string JsEncode(string filename, int offset)
        {
            string js = WebTools.FileObj.ReadFile(HttpContext.Current.Request.MapPath(string.Format("/tmp/{0}", filename)));
            int length = js.Length;

            js = RemoveAnnotation(js);

            WebTools.FileObj.WriteFile(System.Web.HttpContext.Current.Request.MapPath("tmp.js"), js);

            StringBuilder sb = new StringBuilder(js);
           
            sb.Replace(@"\r", " "); //\n替换为空格
            sb.Replace(@"\n", " "); //\n替换为空格
            sb.Replace(Environment.NewLine, " ");
            sb.Replace((char)13, (char)32);
            sb.Replace((char)10, (char)32);
            sb.Replace(@"\", @"\\");    //\替换为\\
            sb.Replace(@"'", @"\'");    // '替换为\'
            js = sb.ToString();
            Regex regex = new Regex(@"([\w\$]+)");            
            MatchCollection matches = regex.Matches(js);
            string element = "";
            List<string> dict = new List<string>();
            int index = 0;
            StringBuilder encscript = new StringBuilder(js);
            StringBuilder dicttab = new StringBuilder();

            foreach (Match match in matches)
            {
                element = match.Groups[1].Value;
                index = dict.FindIndex(m => m.Equals(element));
                if ( index < 0)
                {
                    dict.Add(element);
                    index = dict.Count - 1;
                }
                encscript.Replace(element, Base64Encode(offset + index + 1));
                //regex.Replace(js,element, Base64Encode(offset + index + 1));
            }

            foreach(string d in dict)
            {
                dicttab.AppendFormat("{0}|", d);
            }

            string dictstr = dicttab.ToString().TrimEnd('|');   //字典字符串,删除最后一个|

            string res = formatCode(encscript.ToString(), dictstr, dict.Count, offset);

            return res;
        }

        /// <summary>
        /// 仿Base64
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private string Base64Encode(int c)
        { 
            string res="";
            if (c < 0) throw new Exception("Error:Offset必须>=0.");
            if (c > 63)
                res = Base64Encode(c >> 6) + Base64Encode(c & 63);
            else {
                //为了配合appendReplacement方法的使用,将$替换为\$
                res = c.Equals(63) ? @"\$" : ENCODE_BASE64[c].ToString();
            }
            return res;
        }

        private string formatCode(string enc, string dict, int size, int offset)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("/* Power by Shoresoft.Cn */\neval(function(E,I,A,D,J,K,L,H){function C(A){return A<62?String.fromCharCode(A+=A<26?65:A<52?71:-4):A<63?'_':A<64?'$':C(A>>6)+C(A&63)}while(A>0)K[C(D--)]=I[--A];function N(A){return K[A]==L[A]?A:K[A]}if(''.replace(/^/,String)){var M=E.match(J),B=M[0],F=E.split(J),G=0;if(E.indexOf(F[0]))F=[''].concat(F);do{H[A++]=F[G++];H[A++]=N(B)}while(B=M[G]);H[A++]=F[G]||'';return H.join('')}return E.replace(J,N)}(");
            sb.Append("'" + enc + "',");
            sb.Append("'" + dict + "'.split('|'),");
            sb.Append(size + "," + (size + offset) + ",/[\\w\\$]+/g, {}, {}, []))");
            return sb.ToString();
        }

        /// <summary>
        /// 移除块注释
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string RemoveAnnotation(string str)
        {
            string result = str;
            int start = 0;
            int end = 0;
            start = str.IndexOf("/*");
            end = str.IndexOf("*/");
            StringBuilder sb = new StringBuilder(str);
            if (start >= 0 && end>start)
            {
                sb.Remove(start, end - start + 2);
                return RemoveAnnotation(sb.ToString());
            }
            else
                return sb.ToString();
        }
    }

plupload多文件上传插件上传文件出现blob的问题处理

第一次使用plupload,上传文件后发现出现了一个blob文件,同时有的文件并没有被上传上,这是什么鬼,大概的搜了下,有遇到这个问题的,不过没有几个实质性的解决了的这个问题还是得靠自己了。

观察了下plupload的参数,有一项引起了我的怀疑,那就是chunk_size : '1mb',这项设置是什么鬼?查了下,chunk_size 用来设置块的大小,也就是把一个文件分成这么大的块来进行上传,看来问题就是出在这儿了。把这项设置的值加大,改成10mb或者100mb,再测试就没这问题了。

说下原因:
chunk_size 可以把文件分成多块来上传,这样可以绕过服务器允许的最大上传文件大小的限制,前提是需要上传接口支持文件续传。这个参数一般设置成与服务器允许的最大文件大小一致就可以了,或者是上传接口支持文件续传。

关于在IIS下的.NET网站出现应用池挂掉的Bug排查方法

环境:MVC4+IIS7

现象:测试的时候没有显现出来,当运行到生产环境出现大量访问量的情况下,会出现如下错误:


如果应用程序池挂掉的话,可以肯定的是,代码出现了很严重的错误,导致程序挂了,原因可能是死循环之类的。而又是个别现象引起,测不出来,只能想其他的办法了。

解决方法

首先,在服务器端:

1.开启Windows Error Reporting Service服务

2.执行下面的注册表脚本,在w3wp.exe程序挂掉的时候,自动将dump文件保存到D:\dumps文件夹中:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe]
"DumpFolder"=hex(2):64,00,3a,00,5c,00,64,00,75,00,6d,00,70,00,73,00,00,00
"DumpCount"=dword:00000002
"DumpType"=dword:00000002

3.记录出问题的w3wp.exe程序的pid,把生成的dump文件复制到本地,进行调试。

之后,在本机:

1.双击从服务器上拿下来的dump文件,使用vs(2013、2015等,2010、2008没有测试过)打开,之后会显示出异常摘要等信息。

2.点击右侧“操作”列中的“设置符号路径”菜单

3.通过菜单“视图”——“解决方案资源管理器”,打开解决方案管理器,之后打开解决方案的属性页,选择调试源文件,之后新加一行,选择对应的源代码(项目)文件夹,之后确定保存。

4.回到dump文件摘要页面,通过右侧“操作”菜单下的“使用仅限托管进行调试”菜单进行调试,可以定位到问题代码位置进行解决处理。当然根据问题的不同,还可以选择其他几个调试方法。

以上。

.Net Core系列教程(五)—— Token Base身份认证

在ASP.Net Core中实现一个Token Base身份认证,使用场景主要就是Web API下,可以调用Web API的不止是浏览器,还有各种各样的客户端,有些客户端没有Cookies,也无法使用Session。这时候就需要Token来救场了,相比Cookies,Token更开放,而安全性也要比Cookies高很多。

下面使用微软JwtSecurityTokenHandler来实现一个基于beare token的身份认证。

1.创建辅助类:

在项目中,新建一个Auth文件夹,在Auth文件夹中添加一个RSAKeyHelper类:

using System.Security.Cryptography;
namespace Biz126.WebAPI.Auth
{
    public class RSAKeyHelper
    {
        public static RSAParameters GenerateKey()
        {
            using (var key = new RSACryptoServiceProvider(2048))
            {
                return key.ExportParameters(true);
            }
        }
    }
}

和TokenAuthOption类:

using Microsoft.IdentityModel.Tokens;
namespace Biz126.WebAPI.Auth
{
    public class TokenAuthOption
    {
        public static string Audience { get; } = "ExampleAudience";
        public static string Issuer { get; } = "ExampleIssuer";
        public static RsaSecurityKey Key { get; } = new RsaSecurityKey(RSAKeyHelper.GenerateKey());
        public static SigningCredentials SigningCredentials { get; } = new SigningCredentials(Key, SecurityAlgorithms.RsaSha256Signature);
        public static TimeSpan ExpiresSpan { get; } = TimeSpan.FromMinutes(20);
    }
}

2.修改Startup.cs文件:

打开Startup.cs文件,在ConfigureServices中添加:

            services.AddAuthorization(auth =>
            {
                auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌)
                    .RequireAuthenticatedUser().Build());
            });

完整的ConfigureServices方法:

        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);
            services.Configure<Biz126.Models.ConnectionStrings>(Configuration.GetSection("ConnectionStrings"));    //这个是取数据库配置,与本例无关
            services.AddAuthorization(auth =>
            {
                auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌)
                    .RequireAuthenticatedUser().Build());
            });

            services.AddMvc();
        }

修改Configure方法,在其中增加:

            app.UseExceptionHandler(appBuilder => {
                appBuilder.Use(async (context, next) => {
                    var error = context.Features[typeof(IExceptionHandlerFeature)] as IExceptionHandlerFeature;
                    //when authorization has failed, should retrun a json message to client
                    if (error != null && error.Error is SecurityTokenExpiredException)
                    {
                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            //new { authenticated = false, tokenExpired = true }
                            new { Status = false, Message = "Token已失效", Code = -401, Result = new { tokenExpired = true } }
                        ));
                    }
                    //when orther error, retrun a error message json to client
                    else if (error != null && error.Error != null)
                    {
                        context.Response.StatusCode = 500;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            //new { success = false, error = error.Error.Message }
                            new { Status = false, Code = -500, Message = error.Error.Message }
                        ));
                    }
                    //when no error, do next.
                    else await next();
                });
            });
            app.UseExceptionHandler(appBuilder => {
                appBuilder.Use(async (context, next) => {
                    var error = context.Features[typeof(IExceptionHandlerFeature)] as IExceptionHandlerFeature;
                    //when authorization has failed, should retrun a json message to client
                    if (error != null && error.Error is SecurityTokenExpiredException)
                    {
                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            new { Status = false, Message = "Token已失效", Code = -401, Result = new { tokenExpired = true } }
                        ));
                    }
                    //when orther error, retrun a error message json to client
                    else if (error != null && error.Error != null)
                    {
                        context.Response.StatusCode = 500;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            new { Status = false, Code = -500, Message = error.Error.Message }
                        ));
                    }
                    //when no error, do next.
                    else await next();
                });
            });
            //应用JwtBearerAuthentication
            app.UseJwtBearerAuthentication(new JwtBearerOptions
            {
                TokenValidationParameters = new TokenValidationParameters
                {
                    IssuerSigningKey = TokenAuthOption.Key,
                    ValidAudience = TokenAuthOption.Audience,
                    ValidIssuer = TokenAuthOption.Issuer,
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.FromMinutes(0)
                }
            });

完整的Configure方法:

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();
            app.UseApplicationInsightsRequestTelemetry();
            app.UseApplicationInsightsExceptionTelemetry();
            app.UseExceptionHandler(appBuilder => {
                appBuilder.Use(async (context, next) => {
                    var error = context.Features[typeof(IExceptionHandlerFeature)] as IExceptionHandlerFeature;
                    //when authorization has failed, should retrun a json message to client
                    if (error != null && error.Error is SecurityTokenExpiredException)
                    {
                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            //new { authenticated = false, tokenExpired = true }
                            new { Status = false, Message = "Token已失效", Code = -401, Result = new { tokenExpired = true } }
                        ));
                    }
                    //when orther error, retrun a error message json to client
                    else if (error != null && error.Error != null)
                    {
                        context.Response.StatusCode = 500;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            //new { success = false, error = error.Error.Message }
                            new { Status = false, Code = -500, Message = error.Error.Message }
                        ));
                    }
                    //when no error, do next.
                    else await next();
                });
            });
            app.UseExceptionHandler(appBuilder => {
                appBuilder.Use(async (context, next) => {
                    var error = context.Features[typeof(IExceptionHandlerFeature)] as IExceptionHandlerFeature;
                    //when authorization has failed, should retrun a json message to client
                    if (error != null && error.Error is SecurityTokenExpiredException)
                    {
                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            new { Status = false, Message = "Token已失效", Code = -401, Result = new { tokenExpired = true } }
                        ));
                    }
                    //when orther error, retrun a error message json to client
                    else if (error != null && error.Error != null)
                    {
                        context.Response.StatusCode = 500;
                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(
                            new { Status = false, Code = -500, Message = error.Error.Message }
                        ));
                    }
                    //when no error, do next.
                    else await next();
                });
            });
            app.UseJwtBearerAuthentication(new JwtBearerOptions
            {
                TokenValidationParameters = new TokenValidationParameters
                {
                    IssuerSigningKey = TokenAuthOption.Key,
                    ValidAudience = TokenAuthOption.Audience,
                    ValidIssuer = TokenAuthOption.Issuer,
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.FromMinutes(0)
                }
            });
            app.UseMvc();
        }

3.登录授权接口

在Controllers中,增加TokenAuthController的Web API控制器,在该控制器下添加如下方法:

        /// <summary>
        /// 生成Token
        /// </summary>
        /// <param name="user"></param>
        /// <param name="serviceid"></param>
        /// <param name="device"></param>
        /// <param name="expires"></param>
        /// <returns></returns>
        private string GenerateToken(Biz126.Customer.Models.Detail user,string serviceid,string device, DateTime expires)
        {
            var handler = new JwtSecurityTokenHandler();
            ClaimsIdentity identity = new ClaimsIdentity(
                new GenericIdentity(user.UserName, "TokenAuth"),
                new[] {
                    new Claim("ID", user._Id.ToString()),
                    new Claim("TrueName",user.TrueName),
                    new Claim("ServiceId",serviceid),
                    new Claim("Device",device)  //绑定硬件号
                }
            );
            var securityToken = handler.CreateToken(new SecurityTokenDescriptor
            {
                Issuer = TokenAuthOption.Issuer,
                Audience = TokenAuthOption.Audience,
                SigningCredentials = TokenAuthOption.SigningCredentials,
                Subject = identity,
                Expires = expires
            });
            return handler.WriteToken(securityToken);
        }

正如注释中所说的,该方法用于生成Token。

还是在该控制器下,继续添加GetAuthorize方法,用于取得授权,代码如下:

        [HttpPost]
        public Biz126.Models.ResultModel<object> GetAuthorize(Biz126.Authorization.Models.UserAuth user)
        {
            var result = new Biz126.Models.ResultModel<object>();
            var log = new Biz126.Customer.Models.Login() { UserName = user.UserName, Password = user.Password };
            var login = _users.Login(log);    //登录

            if (login.Status)
            {
                //用户账号状态正常
                //1.查看该用户有几个有效的该授权
                //2.已经开通了几个
                //3.在剩余范围内
                //4.查看该机器是否已经有过授权
                //5.如果已经有过授权,更新Token,如果没有过授权,增加新授权
                var requestAt = DateTime.Now;
                var expiresIn = requestAt + TokenAuthOption.ExpiresSpan;    //过期时间(正常为授权结束日期)
                var token = GenerateToken(login.Result,user.ServiceId,user.Device, expiresIn);
                result.Result = new { requestAt = requestAt, expiresIn = TokenAuthOption.ExpiresSpan.TotalSeconds, accessToken = token };
                result.Status = true;
                result.Message = "success";
                result.Code = 0;
            }
            else
            {
                result.Status = false;
                result.Message = "用户名或密码错误";
                result.Code = -403;
            }
            return result;
        }

4.验证授权:

在Controllers中新建一个CheckAuthController的Web API控制器,添加下面的方法:

        [Authorize("Bearer")]
        public string Post()
        {
            var claimsIdentity = User.Identity as ClaimsIdentity;
            var id = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "ID").Value;
            var device= claimsIdentity.Claims.FirstOrDefault(c => c.Type == "Device").Value;
            return $"Hello! {HttpContext.User.Identity.Name}, your Device is:{device}";
        }

5.测试:

打开Postman,先访问/api/TokenAuth/GetAuthorize,使用用户名和密码进行登录,接口会返回生成的Token,记下返回的Token。继续使用Postman工具,访问接口/api/CheckAuth,在Headers中,添加:Authorization:Bearer 上一步生成的Token,如下图所示

要注意“Bearer”与后面的Token之间有一个空格,之后提交请求,可以看到验证通过并给返回相应的信息。

上面代码只是一个例子,具体可以灵活的运用到自己的项目中。

以上。

分类

最新文章

最近回复

  • 青山: 某种原因,暂停友链,抱歉。
  • 青山: 计划搬迁到腾讯云,正...
  • 老徐: 具体要哪个呢?
  • 老徐: 是不是有点老?
  • 青山: 哇,林志炫
  • 老白: 哇,这改的可以,能不...
  • 老徐: 23333
  • 许建华: 我是为了表情包来的~
  • vultr vps: 感谢分享深入学习
  • 青山: 每一次都是不同的感受

归档

标签云

C# .net core asp.net 情感 SQL mongodb sql server EasyUI 安全 激活 linux 身份验证 https typecho .net sql注入 kms MVC IIS 高并发 IE 坑爹 服务器 mysql Oracle Combobox Datagrid 口语 数据抓取

其它