标签 asp.net 下的文章

ASP.Net Core 2.0 在Linux下连接SQL Server数据库问题

在ASP.Net Core 2.0下,通过Dapper来使用SQL Server数据库,在Windows系统下完全正常,而部署到Linux服务器上会出现连不上数据库的情况,从日志里看,报下面的错误:

Connection Timeout Expired. The timeout period elapsed during the post-login phase. The connection could have timed out while waiting for server to complete the login process and respond; Or it could have timed out while attempting to create multiple active connections. The duration spent while attempting to connect to this server was - [Pre-Login] initialization=23; handshake=365; [Login] initialization=0; authentication=2; [Post-Login] complete=28022;

连接超时。开始的时候怀疑是防火墙的原因,检查了一下防火墙正常,而且通过telnet命令检查数据库的1433端口是通的,看来问题是出在.net core上。
通过百度和Google搜索相关的关键字,找到了一篇帖子:《Timeout Connecting to SQL Server instance from Linux》,说的是只有SQL Server 2008 及之前的版本会有这问题,SQL Server 2012及之后修复了这个问题。
检查了下自己的SQL数据库版本,是SQL Server 2008 R2 版的,正在此列。开了腾讯云的SQL Server云数据库连接测试,完全正常。

以上。

关于ASP.NET MVC中使用Forms验证的问题

表单验证(Forms验证)是一个基于票据(ticket-based)[也称为基于令牌(token-based)]的系统。这意味着当用户登录系统以后,他们得到一个包含基于用户信息的票据(ticket)。这些信息被存放在加密过的cookie里面,这些cookie和响应绑定在一起,因此每一次后续请求都会被自动提交到服务器。

当用户请求匿名用户无法访问的ASP.NET页面时,ASP.NET运行时验证这个表单验证票据是否有效。如果无效,ASP.NET自动将用户转到登录页面。这时就该由你来操作了。你必须创建这个登录页面并且验证由登录页面提交的凭证。如果用户验证成功,你只需要告诉ASP.NET架构验证成功(通过调用FormsAuthentication类的一个方法),运行库会自动设置验证cookie(实际上包含了票据)并将用户转到原先请求的页面。通过这个请求,运行库检测到验证cookie中包含一个有效票据,然后赋给用户对这个页面的访问权限。

下面,就是具体的实现。我们先写一个生成用户票据的方法:

//生成Token并保存到Cookies中
private void CreateToken(Models.User user)
{
    string json = JsonConvert.SerializeObject(user);
    FormsAuthentication.SetAuthCookie(user.UserName.Trim(), true, FormsAuthentication.FormsCookiePath);
    FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(12), false, json);
    Biz126.Cache.SetCookies.AddCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(Ticket));
}

其中Biz126.Cache.SetCookies.AddCookie是我自己封装的保存Cookie方法。
生成Token并保存到Cookie中的方法我们已经写好了,只要在登录成功之后直接调用这个方法就可以了。

下面是验证票据,验证票据,我们放在过滤器中进行验证。
新建AuthenticationAttribute类,继承ActionFilterAttribute,重写OnActionExecuting方法:

        /// <summary>
        /// 检查用户是否有该Action执行的操作权限
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            Models.ResultModel<object> result = new Models.ResultModel<object>();
            result.code = -401;
            result.message = "请登录后进行操作";
            result.status = false;
            //如果存在身份信息
            if (!HttpContext.Current.User.Identity.IsAuthenticated)
            {
                filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized, result, "application/json");
            }
            else
            {                
                
                BLL.IManager manager = new BLL.Manage.Manager();
                result = manager.Detail();    //取当前登录的用户信息,进行其他的操作,比如判断有没有权限等,这里省略
                //。。。省略掉其他的操作
                
                if (!result.status)
                {
                    filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized, result, "application/json");
                    //filterContext.Result = redirect;
                }
            }
        }

之后,在要在需要用户登录的Action上面,加上[Authentication]就可以了,也可以新加一个控制器,如BaseWebApiController,在这个控制器上加上[Authentication],其他的控制器都继承BaseWebApiController,在不需要验证的Action上加上[AllowAnonymous]就可以了。
下面是通过票据取得用户信息:

            if (HttpContext.Current.Request.IsAuthenticated)//是否通过身份验证
            {
                HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];//获取cookie
                FormsAuthenticationTicket Ticket = FormsAuthentication.Decrypt(authCookie.Value);//解密
                string json = Ticket.UserData;//反序列化
                Models.Models.User user = new Models.User();
                try
                {
                    user = JsonConvert.DeserializeObject<Models.User>(json);
                    result.data = user;
                    result.message = "success";
                    result.status = true;
                }
                catch
                {

                }

            }

还需要在web.config中增加配置:

  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="~/Users/Login" timeout="2880" />
    </authentication>
  </system.web>

到这里,其本上都已经完成了,但是你会发现,在IE上,会有很多用户登录的时候验证不通过的情况,如果记录日志,会发现HttpContext.Current.Request.IsAuthenticated==false
HttpContext.Current.Request.User为空
而且这种情况只有在IE下才会出现,其他的现代浏览器比如Chrome、Firefox等都很正常。
通过网络搜索,大部分都没给出答案来。其他把配置按下面的方法修改,就可以解决这个问题:

  <system.web>
    <authentication mode="Forms">
      <forms cookieless="UseCookies" loginUrl="~/Users/Login" timeout="2880" />
    </authentication>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>

或者是打开服务器的IIS,按下面的步骤修改:
IIS的“身份证验证”
1.打开IIS,选择自己的站点,之后双击IIS中的“身份验证”功能
设置Forms身份验证
2.选中Forms身份验证,点击右侧操作区的“编辑”菜单,如果没有启用请先点击“启用”
Forms身份验证的默认设置
3.这是Forms身份验证的默认设置,我们需要改动一下
修改之后的Forms身份验证设置
4.按这里修改一下,就可以了。

以上。

ASP.NET Core 2.0下使用log4net记录文件日志

我们知道log4net的日志功能非常强大,而使用方法也比较复杂;在ASP.NET Core 2.0下,可以通过一个第三方的扩展方法来降低我们的使用难度,具体使用方法如下:
我们先新建一个自己的静态类Log4Net,用于之后调用记录日志:

    public static class Log4Net
{
    private static readonly log4net.ILog log =
    log4net.LogManager.GetLogger(typeof(Log4Net));

    static void SetConfig()
    {
        XmlDocument log4netConfig = new XmlDocument();
        log4netConfig.Load(File.OpenRead("log4net.config"));

        var repo = log4net.LogManager.CreateRepository(
            Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));

        log4net.Config.XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
    }

    /// <summary>
    /// 信息
    /// </summary>
    /// <param name="Message"></param>
    public static void LogInfo(string Message)
    {
        if (!log.IsInfoEnabled)
            SetConfig();
        log.Info(Message);
    }

    /// <summary>
    /// 信息
    /// </summary>
    /// <param name="Message"></param>
    /// <param name="ex"></param>
    public static void LogInfo(string Message, Exception ex)
    {
        if (!log.IsInfoEnabled)
            SetConfig();
        log.Info(Message, ex);
    }

    /// <summary>
    /// 错误日志
    /// </summary>
    /// <param name="Message"></param>
    public static void ErrorInfo(string Message)
    {
        if (!log.IsErrorEnabled)
            SetConfig();
        log.Error(Message);
    }

    /// <summary>
    /// 错误日志
    /// </summary>
    /// <param name="Message"></param>
    /// <param name="ex"></param>
    public static void Error(Exception ex)
    {
        if (!log.IsInfoEnabled)
            SetConfig();
        log.Error("异常", ex);
    }

    /// <summary>
    /// 错误日志
    /// </summary>
    /// <param name="Message"></param>
    /// <param name="ex"></param>
    public static void ErrorInfo(string Message, Exception ex)
    {
        if (!log.IsErrorEnabled)
            SetConfig();
        log.Error(Message, ex);
    }

    /// <summary>
    /// Debug日志
    /// </summary>
    /// <param name="Message"></param>
    public static void DebugInfo(string Message)
    {
        if (!log.IsDebugEnabled)
            SetConfig();
        log.Debug(Message);
    }

    /// <summary>
    /// Debug日志
    /// </summary>
    /// <param name="Message"></param>
    /// <param name="ex"></param>
    public static void DebugInfo(string Message, Exception ex)
    {
        if (!log.IsDebugEnabled)
            SetConfig();
        log.Debug(Message, ex);
    }

    /// <summary>
    /// 警告
    /// </summary>
    /// <param name="Message"></param>
    public static void WarnInfo(string Message)
    {
        if (!log.IsWarnEnabled)
            SetConfig();
        log.Warn(Message);
    }

    /// <summary>
    /// 警告
    /// </summary>
    /// <param name="Message"></param>
    /// <param name="ex"></param>
    public static void WarnInfo(string Message,Exception ex)
    {
        if (!log.IsWarnEnabled)
            SetConfig();
        log.Warn(Message,ex);
        
    }

    /// <summary>
    /// 致命错误
    /// </summary>
    /// <param name="Message"></param>
    public static void FataInfo(string Message)
    {
        if (!log.IsFatalEnabled)
            SetConfig();
        log.Fatal(Message);
    }

    /// <summary>
    /// 致命错误
    /// </summary>
    /// <param name="Message"></param>
    /// <param name="ex"></param>
    public static void FataInfo(string Message,Exception ex)
    {
        if (!log.IsFatalEnabled)
            SetConfig();
        log.Fatal(Message, ex);
    }

该类下需要通过NuGet安装下面几个扩展:

  1. Microsoft.Extensions.Logging

  2. Microsoft.Extensions.Logging.Log4Net.AspNetCore

  3. log4net

之后log4net.config配置文件内容:

<log4net>
    <appender name="Console" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <!-- Pattern to output the caller's file name and line number -->
            <conversionPattern value="%5level [%thread] - STACK: %exception{stacktrace} - MESSAGE: %message%newline" />
        </layout>
    </appender>

    <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
        <!--<file value="Log4Net" />
        <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="yyyyMMdd&quot;.log&quot;" />
        <maximumFileSize value="100KB" />
        <maxSizeRollBackups value="2" />-->
    <param name="File" value="logfile/" />
    <param name="AppendToFile" value="true" />
    <param name="RollingStyle" value="Date" />
    <param name="DatePattern" value="yyyyMMdd&quot;.log&quot;" />
    <param name="StaticLogFileName" value="false" />

        <layout type="log4net.Layout.PatternLayout">
            <!--<conversionPattern value="%level %thread - STACK: %exception{stacktrace} - MESSAGE: %message%newline" />-->
      <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
        </layout>
    </appender>

    <root>
        <level value="ALL" />
        <appender-ref ref="Console" />
        <appender-ref ref="RollingFile" />
    </root>
</log4net>

最后,修改Startup.cs文件的Configure方法,增加新参数如下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

在Configure方法中,添加:

loggerFactory.AddLog4Net();

完整如下:

        // 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)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            loggerFactory.AddLog4Net();

            app.UseStaticFiles();

            app.UseMvc();
        }

测试:
我们写个测试的来看看,在Program类的静态方法中,添加段代码测试一下:

        public static void Main(string[] args)
        {
            Logger.Log4Net.LogInfo("test测试");

            try
            {
                int a = 5;
                int b = 1 / (a - 5);
            }
            catch (Exception e)
            {
                Logger.Log4Net.ErrorInfo("异常信息", e);
            }
            BuildWebHost(args).Run();
        }

运行之后,我们会在根目录下的logfile文件夹中,看到出现了一个日志文件:20180513.log
打开,内容如下:

2018-05-13 22:43:12,039 [1] INFO  Biz126.Logger.Log4Net - test测试
2018-05-13 22:43:12,930 [1] ERROR Biz126.Logger.Log4Net - 异常信息
System.DivideByZeroException: Attempted to divide by zero.
   at Biz126.WebAPI.Program.Main(String[] args) in D:\Items\Log测试\Biz126.WebAPI\Program.cs:line 23
2018-05-13 22:43:18,274 [5] INFO  Microsoft.AspNetCore.Hosting.Internal.WebHost - Request starting HTTP/1.1 GET http://localhost:65176/api/values  
2018-05-13 22:43:18,753 [5] INFO  Microsoft.AspNetCore.Hosting.Internal.WebHost - Request finished in 479.9045ms 404 

符合预期,以上。

ASP.NET Core 2.0 WebAPI 跨域问题

关于 asp.net core 2.0 webapi的跨域,我们这里使用CORS来实现,不使用旧的JSONP,可以这样配置:
打开 Startup.cs文件,转到ConfigureServices(IServiceCollection services) 中,增加:

services.AddCors(options =>
{
    options.AddPolicy("AnyOrigin", builder =>
    {
        builder
            .AllowAnyOrigin()
            .AllowAnyMethod();
    });
});

再转到Configure(IApplicationBuilder app, IHostingEnvironment env)中,增加:

app.UseCors("AnyOrigin");

就可以开启CORS跨域了。
关于ASP.Net Core的CORS跨域问题详细的使用方法,请参考《Enable Cross-Origin Requests (CORS) in ASP.NET Core》一文。
下面测试一下:

<html>
    <head>
        
    </head>
    <body>
        
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
        <script>
            $(function(){
                $.ajax({
                    url:"http://domain/api/Mall/Category/List",
                    data:{id:1},
                    dataType:"json",
                    type:"post",
                    success:function(result){
                        console.log(result);
                    }
                });
            });
        </script>
    </body>
</html>

直接双击通过浏览器打开这个页面,可以看到,已经读到远程接口的数据了:
console
network
以上。

.Net网站下使用Oracle数据库的环境设置

在.Net网站下使用Oracle,需要网站服务器安装Oracle数据库的客户端,这是目前必须要安装的。
以下是在Windows Server 2008 R2服务器环境下的设置方法及注意事项,其他系统可能会略有不同。
1.服务器需要安装Oracle数据库的客户端,版本为Oracle Database 11g Release 1,而且只能使用这个版本,其他版本不可行,另外需要与你的网站应用池的位数(32位或64位)一致;
2.安装时,安装类型选择“运行时”;
3.安装完成后,查看环境变量中,有没有把安装目录下的BIN文件夹添加到环境变量中,如:D:\app\Administrator\product\11.2.0\client_1\bin;;
4.打开安装目录右键属性,切换到“安全”选项卡,编辑,选中“Authenticated Users“,把”读取和执行“权限去掉,之后再重新勾选,之后”应用“;
5.最后一步,也是重要的一步,那就是重启服务器,不重启服务器不会生效。

这就可以了。

分类

最新文章

最近回复

  • 老徐: 已经加上了,抱歉才看到
  • 青山: 某种原因,暂停友链,抱歉。
  • 搬瓦工: 朋友 交换链接吗
  • 飞刀说: 名称:飞刀说 描述:...
  • 青山: 计划搬迁到腾讯云,正...
  • 河边的飞刀: 网站名称:飞刀说 网...
  • 老徐: 具体要哪个呢?
  • 老徐: 是不是有点老?
  • 青山: 哇,林志炫
  • 老白: 哇,这改的可以,能不...

归档

标签云

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

其它