比赛规则
1.统一使用Realse版本的最新 DLL,Realse模式启用程序
2.为了平衡CPU和数据库空闲情况,使用车轮战,每场比赛连续10回合比试
3.多次重启电脑取平均成绩上图
比赛成员
1.SqlSugar 3.1.01
2.Dapper 1.5.0.2 Dapper.Contrib 1.5 官方DLL
View Details用户登录是一个非常常见的应用场景 .net core 2.0 的登录方式发生了点变化,应该是属于是良性的变化,变得更方便,更容易扩展。 配置 打开项目中的Startup.cs文件,找到ConfigureServices方法,我们通常在这个方法里面做依赖注入的相关配置。添加如下代码:
|
1 2 3 4 5 6 7 8 9 |
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => { o.LoginPath = new PathString("/Account/Login"); o.AccessDeniedPath = new PathString("/Error/Forbidden"); }); } |
这段代码的大概意思就是,添加授权支持,并添加使用Cookie的方式,配置登录页面和没有权限时的跳转页面。 再找到Configure方法,添加 app.UseAuthentication(),使用授权:
|
1 2 3 4 |
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseAuthentication(); } |
这样基本的配置就完成了。 登录 添加一个Controller,如AccountController,再添加一个Action,如 Login,所配置的路由,要与上面的配置对应,不然跳转登录时会跳错页面。 用户提交用户名和密码,登录代码大致如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[HttpPost] public async Task <IActionResult> Login(string userName, string password, string ReturnUrl) { var user = _userService.Login(userName, password); if (user != null) { user.AuthenticationType = CookieAuthenticationDefaults.AuthenticationScheme; var identity = new ClaimsIdentity(user); identity.AddClaim(new Claim(ClaimTypes.Name, user.UserID)); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); if (ReturnUrl.IsNullOrEmpty()) { return RedirectToAction("Index", "Dashboard"); } return Redirect(ReturnUrl); } ViewBag.Errormessage = "登录失败,用户名密码不正确"; return View(); } |
这里要注意的是 AuthenticationType 所设置的Scheme一定要与前面的配置一样,这样对应的登录授权才会生效。 使用登录身份 登录的目录,就是希望有些页面或者资源只有登录以后才可访问。使用AuthorizeAttribute来做限制。在需要做限制的Controller上加上[Authorize]特性来做限制。
|
1 2 3 4 |
[Authorize] public class ThemeController { } |
这样这个Controller下的所有的Action都必需要登录后才可访问。如果希望其中某些Action可以不用登录也可访问,可以添加例外:
|
1 2 3 4 5 |
[AllowAnonymous] public ActionResult Index() { return View(); } |
到这里一个最基础的登录就完成了。 在Web项目中,通常会遇到一个问题,后端管理员和前台用户。这两个用户都是可登录的,在 .net core 2.0,这个将很容易实现。 多用户登录 添加一个登录方案(Scheme) CookieAuthenticationDefaults.AuthenticationScheme,这是系统已经定义好的一个默认的登录方案,添加一个新的来实现一个不同的身份登录。代码如下:
|
1 2 3 4 5 6 7 8 |
public class CustomerAuthorizeAttribute : AuthorizeAttribute { public const string CustomerAuthenticationScheme = "CustomerAuthenticationScheme"; public CustomerAuthorizeAttribute() { this.AuthenticationSchemes = CustomerAuthenticationScheme; } } |
添加使用这个新的方案,在Startup.cs文件下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => { o.LoginPath = new PathString("/Account/Login"); o.AccessDeniedPath = new PathString("/Error/Forbidden"); }) .AddCookie(CustomerAuthorizeAttribute.CustomerAuthenticationScheme, option => { option.LoginPath = new PathString("/Account/Signin"); option.AccessDeniedPath = new PathString("/Error/Forbidden"); }); } |
添加新的登录方案,并配置一个新的登录页面,登录的方法和刚才是一样,只是AuthenticationType使用了新的方案。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[HttpPost] public async Task <IActionResult> Login(string userName, string password, string ReturnUrl) { var user = _userService.Login(userName, password); if (user != null) { user.AuthenticationType = <strong>CustomerAuthorizeAttribute.CustomerAuthenticationScheme</strong>; var identity = new ClaimsIdentity(user); identity.AddClaim(new Claim(ClaimTypes.Name, user.UserID)); await HttpContext.SignInAsync(<strong>CustomerAuthorizeAttribute.CustomerAuthenticationScheme</strong>, new ClaimsPrincipal(identity)); if (ReturnUrl.IsNullOrEmpty()) { return RedirectToAction("Index", "Dashboard"); } return Redirect(ReturnUrl); } ViewBag.Errormessage = "登录失败,用户名密码不正确"; return View(); } |
验证登录状态 使用方法和之前的差不多,换成新的CustomerAuthorizeAttribute就行了:
|
1 2 3 4 |
[CustomerAuthorize] public class CustomerController { } |
CustomerAuthorizeAttribute这个类,不是必需的,只是为了方便使用而写,其实完全可以只定义一个新的方案(Scheme)就行了。 谁才是HttpContext.User? 登录了多个用户,那么谁才是HttpContext.User呢?如果你的Controller或者Action上有使用AuthorizeAttribute,那这个Attribute使用的登录方案是哪个,则这个HttpContext.User对应的就是那个方案的登录用户。如果没有使用,则AddAuthentication()方法默认指它的方案(Scheme)所登录的用户,就是这个HttpContext.User了。 如何获取对应方案的登录用户呢?使用HttpContext.AuthenticateAsync
|
1 2 3 4 5 |
var auth = await HttpContext.AuthenticateAsync(CustomerAuthorizeAttribute.CustomerAuthenticationScheme); if (auth.Succeeded) { auth.Principal.Identity... } |
退出登录 这个就简单了,指定方案退出就可以了。
|
1 2 3 4 5 |
public async Task Logout(string returnurl) { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Redirect(returnurl ?? "~/"); } |
from:http://www.zkea.net/codesnippet/detail/asp-net-core-multi-login-user.html
View Details大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cookie中。 现在到了ASP.NET CORE的时代,但是ASP.NET CORE中没有FormsAuthentication这个东西,那么怎么做身份认证呢?答案是ASP.NET CORE已经为我们内置了Cookie身份认证的功能,而且使用起来非常方便,注意本文是基于ASP.NET CORE 2.0版本来阐述Cookie认证方式的。 1.从ASP.NET CORE OWIN框架中启用Cookie身份认证功能 要在ASP.NET CORE中使用Cookie身份认证,第一步就是在项目中的OWIN框架文件Startup.cs中启用Cookie身份认证中间件。 首先我们在Startup中的ConfigureServices方法中使用services.AddAuthentication注册Cookie认证服务,如下代码所示:
|
1 2 3 4 5 6 7 |
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); //注册Cookie认证服务 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(); } |
然后在Startup中的Configure方法中使用app.UseAuthentication启用Cookie认证中间件(注意其中app.UseAuthentication和app.UseMvc的调用顺序不能反),如下代码所示:
|
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 |
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); //注意app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,否者后面就算调用HttpContext.SignInAsync进行用户登录后,使用 //HttpContext.User还是会显示用户没有登录,并且HttpContext.User.Claims读取不到登录用户的任何信息。 //这说明Asp.Net OWIN框架中MiddleWare的调用顺序会对系统功能产生很大的影响,各个MiddleWare的调用顺序一定不能反 app.UseAuthentication(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } |
这里顺便说一下app.UseAuthentication是用来干什么的,app.UseAuthentication会启用Authentication中间件,该中间件会根据当前Http请求中的Cookie信息来设置HttpContext.User属性(后面会用到),所以只有在app.UseAuthentication方法之后注册的中间件才能够从HttpContext.User中读取到值,这也是为什么上面强调app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,因为只有这样ASP.NET Core的MVC中间件中才能读取到HttpContext.User的值。 2.登录用户 在ASP.NET CORE中使用Cookie认证登录用户的方法和传统的FormsAuthentication不太一样,大致步骤如下: 创建Claim类型的数组,将登录用户的所有信息(比如用户名)存储在Claim类型的字符串键值对中 将上面创建的Claim类型的数组传入ClaimsIdentity中,用来构造一个ClaimsIdentity对象 将上面创建的ClaimsIdentity对象传入ClaimsPrincipal中,用来构造一个ClaimsPrincipal对象 调用HttpContext.SignInAsync方法,传入上面创建的ClaimsPrincipal对象,完成用户登录 所以我们可以看到整个ASP.NET CORE的Cookie认证登录流程比以前ASP.NET的FormsAuthentication还是要复杂许多,毕竟以前一个FormsAuthentication.SetAuthCookie方法就搞定了。 在本文的例子中我们在项目中默认的HomeController中创建了一个Acion方法Login,来实现用户登录的代码。当然这里我们实现的是最简的Cookie登录,下面代码中实际上还可以设置Cookie是否持久化、Cookie多久过期、存储登录用户信息的Cookie的名字是什么等,我们就不做过多介绍了,大家可以阅读本文最后推荐的两份官方文档了解更多。 Login方法的代码如下:
|
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 |
/// <summary> /// 该Action登录用户Wangdacui到Asp.Net Core /// </summary> public IActionResult Login() { //下面的变量claims是Claim类型的数组,Claim是string类型的键值对,所以claims数组中可以存储任意个和用户有关的信息, //不过要注意这些信息都是加密后存储在客户端浏览器cookie中的,所以最好不要存储太多特别敏感的信息,这里我们只存储了用户名到claims数组, //表示当前登录的用户是谁 var claims = new[] { new Claim("UserName", "Wangdacui") }; var claimsIdentity = new ClaimsIdentity( claims, CookieAuthenticationDefaults.AuthenticationScheme); ClaimsPrincipal user = new ClaimsPrincipal(claimsIdentity); Task.Run(async () => { //登录用户,相当于ASP.NET中的FormsAuthentication.SetAuthCookie await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user); //可以使用HttpContext.SignInAsync方法的重载来定义持久化cookie存储用户认证信息,例如下面的代码就定义了用户登录后60分钟内cookie都会保留在客户端计算机硬盘上, //即便用户关闭了浏览器,60分钟内再次访问站点仍然是处于登录状态,除非调用Logout方法注销登录。 //注意其中的AllowRefresh属性,如果AllowRefresh为true,表示如果用户登录后在超过50%的ExpiresUtc时间间隔内又访问了站点,就延长用户的登录时间(其实就是延长cookie在客户端计算机硬盘上的保留时间), //例如本例中我们下面设置了ExpiresUtc属性为60分钟后,那么当用户登录后在大于30分钟且小于60分钟内访问了站点,那么就将用户登录状态再延长到当前时间后的60分钟。但是用户在登录后的30分钟内访问站点是不会延长登录时间的, //因为ASP.NET Core有个硬性要求,是用户在超过50%的ExpiresUtc时间间隔内又访问了站点,才延长用户的登录时间。 //如果AllowRefresh为false,表示用户登录后60分钟内不管有没有访问站点,只要60分钟到了,立马就处于非登录状态(不延长cookie在客户端计算机硬盘上的保留时间,60分钟到了客户端计算机就自动删除cookie) /* await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, user, new AuthenticationProperties() { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60), AllowRefresh = true }); */ }).Wait(); return View(); } |
如果当前Http请求本来登录了用户A,现在调用HttpContext.SignInAsync方法登录用户B,那么相当于注销用户A,登录用户B 3.读取登录用户信息 那么用户登录后怎么将登录用户的信息(比如用户名)读取出来呢?我们在HomeController的Index方法中演示了如何判断当前用户是否已经登录,并且读出登录用户的用户名,Index方法的代码如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/// <summary> /// 该Action判断用户是否已经登录,如果已经登录,那么读取登录用户的用户名 /// </summary> public IActionResult Index() { //如果HttpContext.User.Identity.IsAuthenticated为true, //或者HttpContext.User.Claims.Count()大于0表示用户已经登录 if (HttpContext.User.Identity.IsAuthenticated) { //这里通过 HttpContext.User.Claims 可以将我们在Login这个Action中存储到cookie中的所有 //claims键值对都读出来,比如我们刚才定义的UserName的值Wangdacui就在这里读取出来了 var userName = HttpContext.User.Claims.First().Value; } return View(); } |
注意,最好还是用HttpContext.User.Identity.IsAuthenticated来判断用户是否已经登录 4.注销用户 那么登录用户后怎么注销登录呢?我们在HomeController的Logout方法中演示了如何注销登录的用户,代码如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/// <summary> /// 该Action从Asp.Net Core中注销登录的用户 /// </summary> public IActionResult Logout() { Task.Run(async () => { //注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut await HttpContext.SignOutAsync(); }).Wait(); return View(); } |
如果当前Http请求本来就没有登录用户,那么调用HttpContext.SignOutAsync方法时也不会报错 5.负载均衡 警告: ASP.NET Core使用 ASP.NET Core data protection stack 来实现Cookie身份认证。如果在服务器集群中必须配置 ASP.NET Core Data Protection,有关详细信息,请参阅 Configuring data protection。如果你的ASP.NET Core站点使用了负载均衡部署了多个实例,就要做ASP.NET Core Data Protection的配置,否则ASP.NET CORE跨多个实例进行Cookie身份认证会失败。 还可以参考:Host ASP.NET Core in a web farm 以及 Share authentication cookies among ASP.NET apps 如何管理ASP.NET Core Data Protection的过期key,可以查看:Data Protection – […]
View Details一、前方有坑 php在使用加减乘除等运算符计算浮点数的时候,经常会出现意想不到的结果,特别是关于财务数据方面的计算,给不少工程师惹了很多的麻烦。比如今天工作终于到的一个案例: $a = 2586; $b = 2585.98; var_dump($a-$b); 期望的结果是:float(0.02) 实际结果: float(0.019999999999982) 人生有坑,处处提防 二、防坑攻略: 1、通过乘100的方式转化为整数加减,然后在除以100转化回来…… 2、使用number_format转化成字符串,然后在使用(float)强转回来…… 3、php提供了高精度计算的函数库,实际上就是为了解决这个浮点数计算问题而生的。 主要函数有: bcadd — 将两个高精度数字相加 bccomp — 比较两个高精度数字,返回-1, 0, 1 bcdiv — 将两个高精度数字相除 bcmod — 求高精度数字余数 bcmul — 将两个高精度数字相乘 bcpow — 求高精度数字乘方 bcpowmod — 求高精度数字乘方求模,数论里非常常用 bcscale — 配置默认小数点位数,相当于就是Linux bc中的”scale=” bcsqrt — 求高精度数字平方根 bcsub — 将两个高精度数字相减 前两种流氓的办法就不测试了,使用bcsub测试第三种两数相减的例子, 先看bcsub用法(来自官网) string bcsub ( string $left_operand , string $right_operand [, int $scale = int ] ) 参数 left_operand 字符串类型的左操作数. right_operand 字符串类型的右操作数. scale 此可选参数用于设置结果中小数点后的小数位数。也可通过使用 bcscale() 来设置全局默认的小数位数,用于所有函数。 返回值 返回减法之后结果为字符串类型. 测试代码: var_dump(bcsub($a,$b,2)); 结果 0.02 其他的函数请参考PHP官方网站 三、为啥有坑: php的bug?不是,这是所有语言基本上都会遇到的问题,所以基本上大部分语言都提供了精准计算的类库或函数库。 要搞明白这个原因, […]
View Details1 准备 下载 tomcat 首先在 tomcat 官网上下载 windows 版本的 tomcat 包。因为只有 windows 版本中才有用于安装或卸载 Tomcat 服务的 service.bat。 解压为文件夹,假设 tomcat 的解压路径为 ${TOMCAT_HOME} 通过命令行,进入 ${TOMCAT_HOME}/bin 2 安装 Tomcat 服务 输入命令:
|
1 |
service.bat install 服务名 |
这里我们可以把启动类型改为 “自动”,这样如果服务器重启,就会自动启动服务啦。 快速进入 “服务” 列表的方法:win+R 打开运行窗口,然后输入 services.msc 建议把服务的名称加上端口号,这样方便管理哦O(∩_∩)O~ 如果启动服务时报错,查看 tomcat 日志发现是 “不是有效的 Win32 应用程序” 引起的。这可能是操作系统的问题(比如 windows server 2007),这时只需下载一个 32 位的 windows 版的 tomcat 包即可解决。 3 卸载 Tomcat 服务 输入命令:
|
1 |
service.bat remove 服务名 |
是不是很简单呀O(∩_∩)O哈哈~ from:https://blog.csdn.net/deniro_li/article/details/79093390
View DetailsOctober CMS 的后台管理很简单,没有多余的功能。
首页部分是【仪表盘】显示了系统的基本信息。
内容管理系统:这里可以设置页面、部件、布局、内容块、资源和组件。
媒体:是用于管理系统中的各种媒体资源,包括图片、音频、视频、文档等。默认是存储在服务器本地的。我们可以上传这些内容到服务器,也可以建立更多的目录对这些资源进行分别存储。
设置:默认情况下设置里面没有太多的设置,默认包含邮件、日志以及系统和内容功能。我们可以在系统中进行管理员的管理,用于控制用户具有的权限。后面,我们将学习插件是如何工作的。
按照laravel开发环境的要求安装环境,必不可少的是composer了。
在命令行执行
composer create-project october/october octobermovie
上述命令完成后,进入对应的目录,这里执行
cd octobermovie
php artisan october:install
首先是对应的版本
|
1 2 3 4 5 6 |
Laravel <span class="hljs-number">5.1</span> composer <span class="hljs-built_in">require</span> encore/laravel-admin <span class="hljs-string">"1.1.*"</span> Laravel <span class="hljs-number">5.2</span> composer <span class="hljs-built_in">require</span> encore/laravel-admin <span class="hljs-string">"1.2.*"</span> Laravel <span class="hljs-number">5.3</span> composer <span class="hljs-built_in">require</span> encore/laravel-admin <span class="hljs-string">"1.3.*"</span> Laravel <span class="hljs-number">5.4</span> composer <span class="hljs-built_in">require</span> encore/laravel-admin <span class="hljs-string">"1.4.x-dev"</span> Laravel <span class="hljs-number">5.5</span> composer <span class="hljs-built_in">require</span> encore/laravel-admin <span class="hljs-string">"1.5.x-dev"</span> |
我们选用Laravel 5.5 首先安装laravel 5.5
|
1 2 |
composer create-project --prefer-dist laravel/laravel=<span class="hljs-string">'5.5.*'</span> laravel-admin |
2.然后进去laravel-admin文件中
|
1 2 |
<span class="hljs-built_in">cd</span> larabel-admin |
修改.env的数据库连接设置,然后进去config/database,修改mysql的’strict' => true,改为false(mysql5.7的需要改,5.7以下的不需要改) 运行这些命令来发布资产和配置
|
1 2 |
php artisan vendor:publish --provider=<span class="hljs-string">"Encore\Admin\AdminServiceProvider"</span> |
最后运行以下命令来完成安装
|
1 2 |
<span class="hljs-selector-tag">php</span> <span class="hljs-selector-tag">artisan</span> <span class="hljs-selector-tag">admin</span><span class="hljs-selector-pseudo">:install</span> |
配置laravel的nginx重写规则,在nginx配置下加入try_files $uri $uri/ /index.php?$query_string;
|
1 2 3 4 5 6 7 |
location / { root <span class="hljs-string">'/www/laravel-admin/public'</span>; <span class="hljs-comment"># 网站默认首页</span> index index.php index.html index.htm; try_files <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php?<span class="hljs-variable">$query_string</span>; } |
7.打开浏览器输入http://localhost/admin/,使用用户名admin和密码admin登录 作者:Feng_Yikai 链接:https://www.jianshu.com/p/1110a2cad516 来源:简书
View Details创建一个包含变量名和它们的值的数组:
|
1 2 3 4 5 6 7 8 9 |
<?php $firstname = "Peter"; $lastname = "Griffin"; $age = "41"; $result = compact("firstname", "lastname", "age"); print_r($result); ?> |
定义和用法 compact() 函数创建一个包含变量名和它们的值的数组。 注释:任何没有变量名与之对应的字符串都被略过。 from:https://www.runoob.com/php/func-array-compact.html
View Details