Former-commit-id: 25b0340db0330735d7e2ec75a8f6ff728152bb8b
TangShanKaiPing
wanggang 5 years ago
parent b2e44e5399
commit 5a545e925f

@ -1,12 +1,10 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text;
@ -14,7 +12,12 @@ namespace Infrastructure.Extensions
{
public static class HttpContextExtensions
{
public static void SignIn(this HttpContext httpContext, string userName, bool rememberMe, IConfiguration cfg)
public static string GetJwtCookieName(this HttpContext httpContext)
{
return $"jwt-{Assembly.GetEntryAssembly().GetName().Name.ToLower()}";
}
public static void JwtSignIn(this HttpContext httpContext, string userName, bool rememberMe, IConfiguration cfg)
{
var token = httpContext.GetToken(userName, cfg, DateTime.Now.AddYears(1));
var cookieOptions = new CookieOptions
@ -25,8 +28,14 @@ namespace Infrastructure.Extensions
{
cookieOptions.Expires = DateTimeOffset.Now.AddYears(1);
}
httpContext.Response.Cookies.Delete("jwt");
httpContext.Response.Cookies.Append("jwt", token, cookieOptions);
var cookieName = httpContext.GetJwtCookieName();
httpContext.Response.Cookies.Delete(cookieName);
httpContext.Response.Cookies.Append(cookieName, token, cookieOptions);
}
public static void JwtSignOut(this HttpContext httpContext)
{
httpContext.Response.Cookies.Delete(httpContext.GetJwtCookieName());
}
public static string GetToken(this HttpContext httpContext, string userName, IConfiguration cfg, DateTime expires)

@ -267,7 +267,7 @@ namespace Infrastructure.Web
{
if (!context.Request.IsAjax())
{
context.Response.Redirect("Account/Login");
context.Response.Redirect("/Account/Login");
context.HandleResponse();
}
return Task.CompletedTask;
@ -281,9 +281,10 @@ namespace Infrastructure.Web
{
context.Token = context.Request.Query["access_token"];
}
if (!context.Request.Headers.ContainsKey("Authorization") && context.Request.Cookies.Keys.Contains("jwt"))
var jwtCookieName = context.HttpContext.GetJwtCookieName();
if (!context.Request.Headers.ContainsKey("Authorization") && context.Request.Cookies.Keys.Contains(jwtCookieName))
{
context.Token = context.Request.Cookies["jwt"];
context.Token = context.Request.Cookies[jwtCookieName];
}
}
return Task.CompletedTask;

@ -7,26 +7,12 @@ namespace Application.Domain.Entities
[Display(Name = "用户")]
public class User : BaseEntity
{
/// <summary>
/// 登录名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 加密混淆随机数
/// </summary>
public string NickName { get; set; }
public string Avatar { get; set; }
public string SecurityStamp { get; set; }
/// <summary>
/// 加密密码
/// </summary>
public string PasswordHash { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; }
public List<UserRole> UserRoles { get; set; } = new List<UserRole>();
}
}

@ -1,20 +1,15 @@
using Application.Domain.Entities;
using Infrastructure.Data;
using Infrastructure.Extensions;
using Infrastructure.Security;
using Infrastructure.UI;
using Infrastructure.Web;
using IoT.Shared.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoT.UI.Shard
{

@ -19,21 +19,21 @@ namespace IoTCenter.Controllers
[Authorize]
public class AccountController : BaseController
{
private readonly IConfiguration _configuration;
private readonly IConfiguration _cfg;
private readonly IRepository<User> _userRepo;
private readonly IStringLocalizer<Resource> _localizer;
private readonly IEncryptionService _encryptionService;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
public AccountController(IConfiguration configuration,
public AccountController(IConfiguration cfg,
IRepository<User> userRepo,
IEncryptionService encryptionService,
IStringLocalizer<Resource> localizer,
IEmailSender emaliSender,
ISmsSender smsSender)
{
this._configuration = configuration;
this._cfg = cfg;
this._userRepo = userRepo;
this._encryptionService = encryptionService;
this._localizer = localizer;
@ -59,20 +59,51 @@ namespace IoTCenter.Controllers
public IActionResult Logout()
{
var fullReturnUrl = Url.FullAction("Index", "Home");
var logoutUrl = this._configuration["usercenter:logout"];
var logoutUrl = this._cfg["usercenter:logout"];
var url = logoutUrl.SetParam("returnUrl", fullReturnUrl);
return Redirect(url);
}
[AllowAnonymous]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public string JsonpLogin(string userName, string nickName, string avatar, string timestamp, bool rememberMe, string sign)
{
try
{
var key = this._cfg.GetSection("usercenter").GetValue<string>("key");
if (string.Concat(userName, timestamp, key).Md5() == sign)
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
if (user == null)
{
user = new User { UserName = userName, NickName = nickName, Avatar = avatar };
this._userRepo.Add(user);
this._userRepo.SaveChanges();
}
HttpContext.JwtSignIn(userName, rememberMe, _cfg);
return "";
}
else
{
return $"function(){{return \"{userName} login error\";}}();";
}
}
catch (Exception ex)
{
ex.PrintStack();
return $"function(){{return {ex.Message};}}();";
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public string JsonpLogout(string userName, string timestamp, string sign)
{
try
{
var key = this._configuration["usercenter:key"];
var key = this._cfg["usercenter:key"];
if (string.Concat(userName, timestamp, key).Md5() == sign)
{
HttpContext.SignOutAsync();
HttpContext.JwtSignOut();
return "";
}
else
@ -92,7 +123,7 @@ namespace IoTCenter.Controllers
public IActionResult Login(string returnUrl = null)
{
var fullReturnUrl = Url.GetFullUrl(returnUrl ?? "~");
var loginUrl = this._configuration["usercenter:login"];
var loginUrl = this._cfg["usercenter:login"];
var url = loginUrl.SetParam(nameof(returnUrl), fullReturnUrl);
return Redirect(url);
}
@ -136,7 +167,7 @@ namespace IoTCenter.Controllers
public IActionResult Register()
{
var fullReturnUrl = Url.FullAction("Index", "Home");
var registerUrl = this._configuration["usercenter:register"];
var registerUrl = this._cfg["usercenter:register"];
var url = registerUrl.SetParam("returnUrl", fullReturnUrl);
return Redirect(url);
}

@ -171,13 +171,13 @@
<img src="~/images/temperature.png" style="max-width:48px;margin-top:19px;" />
</div>
<div class="col-md-8 col-xs-8" style="height:100px;">
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'温度','Description')==='适中'?'normal':'danger'">
{{GetDeviceDataAttr(device.number,'温度','Description')}}
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'温度','description')==='适中'?'normal':'danger'">
{{GetDeviceDataAttr(device.number,'温度','description')}}
</h3>
</div>
</div>
<div class="row">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">温度:{{GetDeviceDataAttr(device.number,'温度','Value')}}{{ GetDeviceDataAttr(device.number,'温度','Unit')}}</span>
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">温度:{{GetDeviceDataAttr(device.number,'温度','value')}}{{ GetDeviceDataAttr(device.number,'温度','unit')}}</span>
</div>
</div>
</div>
@ -188,13 +188,13 @@
<img src="~/images/humidity.png" style="max-width:48px;margin-top:19px;" />
</div>
<div class="col-md-8 col-xs-8" style="height:100px;">
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'湿度','Description')==='适中'?'normal':'danger'">
{{GetDeviceDataAttr(device.number,'湿度','Description')}}
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'湿度','description')==='适中'?'normal':'danger'">
{{GetDeviceDataAttr(device.number,'湿度','description')}}
</h3>
</div>
</div>
<div class="row">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">湿度:{{GetDeviceDataAttr(device.number,'湿度','Value')}}{{ GetDeviceDataAttr(device.number,'湿度','Unit')}}</span>
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">湿度:{{GetDeviceDataAttr(device.number,'湿度','value')}}{{ GetDeviceDataAttr(device.number,'湿度','unit')}}</span>
</div>
</div>
</div>
@ -208,13 +208,13 @@
<img src="~/images/pm25.png" style="max-width:48px;margin-top:19px;" />
</div>
<div class="col-md-8 col-xs-8" style="height:100px;">
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'PM2.5','Description')==='污染'?'danger':'normal'">
{{GetDeviceDataAttr(device.number,'PM2.5','Description')}}
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'PM2.5','description')==='污染'?'danger':'normal'">
{{GetDeviceDataAttr(device.number,'PM2.5','description')}}
</h3>
</div>
</div>
<div class="row">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">PM2.5{{GetDeviceDataAttr(device.number,'PM2.5','Value')}}{{ GetDeviceDataAttr(device.number,'PM2.5','Unit')}}</span>
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">PM2.5{{GetDeviceDataAttr(device.number,'PM2.5','value')}}{{ GetDeviceDataAttr(device.number,'PM2.5','unit')}}</span>
</div>
</div>
</div>
@ -227,13 +227,13 @@
<img src="~/images/light.png" style="max-width:48px;margin-top:19px;" />
</div>
<div class="col-md-8 col-xs-8" style="height:100px;">
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'光照度','Description')==='适中'?'normal':'danger'">
{{GetDeviceDataAttr(device.number,'光照度','Description')}}
<h3 style="line-height:100px;margin:0;" :class="GetDeviceDataAttr(device.number,'光照度','description')==='适中'?'normal':'danger'">
{{GetDeviceDataAttr(device.number,'光照度','description')}}
</h3>
</div>
</div>
<div class="row">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">光照 {{GetDeviceDataAttr(device.number,'光照度','Value')}}{{ GetDeviceDataAttr(device.number,'光照度','Unit')}}</span>
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">光照 {{GetDeviceDataAttr(device.number,'光照度','value')}}{{ GetDeviceDataAttr(device.number,'光照度','unit')}}</span>
</div>
</div>
</div>
@ -245,12 +245,12 @@
<img src="~/images/person.png" style="max-width:48px;margin-top:19px;" />
</div>
<div class="col-md-8 col-xs-8" style="height:100px;">
<img src="~/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDeviceDataAttr(device.number,'状态','Value')==='警报'" />
<img src="~/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDeviceDataAttr(device.number,'状态','value')==='警报'" />
<h3 style="line-height:100px;margin:0;" class="normal" v-else>正常</h3>
</div>
</div>
<div class="row">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">红外 {{GetDeviceDataAttr(device.number,'状态','Value') }}</span>
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">红外 {{GetDeviceDataAttr(device.number,'状态','value') }}</span>
</div>
</div>
</div>
@ -262,12 +262,12 @@
<img src="~/images/smoke.png" style="max-width:48px;margin-top:19px;" />
</div>
<div class="col-md-8 col-xs-8" style="height:100px;">
<img src="~/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDeviceDataAttr(device.number,'状态','Value')==='警报'" />
<img src="~/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDeviceDataAttr(device.number,'状态','value')==='警报'" />
<h3 style="line-height:100px;margin:0;" class="normal" v-else>正常</h3>
</div>
</div>
<div class="row">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">烟雾 {{GetDeviceDataAttr(device.number,'状态','Value') }}</span>
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">烟雾 {{GetDeviceDataAttr(device.number,'状态','value') }}</span>
</div>
</div>
</div>
@ -333,7 +333,7 @@
<div class="card btns" style="height:220px;">
<div class="card-header">
<h3 class="card-title">
<img src="~/images/light.png" />{{device.DisplayName||device.name}}
<img src="~/images/light.png" />{{device.displayName||device.name}}
</h3>
<div class="card-tools">
<img v-if="GetDataValue(device.number,'状态')=='开'" v-on:click="CallApi(device.number,'/ColorLight/Off')" src="~/images/on.png" />
@ -386,7 +386,7 @@
<div class="card-header" style="padding-bottom:0;">
<h3 class="card-title">
<img src="~/images/control.png" />
{{device.DisplayName||device.name}}
{{device.displayName||device.name}}
</h3>
<ul class="nav nav-tabs card-tools" role="tablist">
<li class="nav-item"><a class="nav-link active" :href="'#tab_1'+device.number" data-toggle="tab">空调</a></li>
@ -534,7 +534,7 @@
<input type="hidden" name="Type" value="5" />
<div class="row">
<div class="col-md-12 col-xs-12">
<label class="btn btn-sm btn-success" v-for="btn in GetButtons(device.number)"><input v-on:click="SendCode1($event)" name="Code" type="radio" :value="btn.Value" />{{btn.name}}</label>
<label class="btn btn-sm btn-success" v-for="btn in GetButtons(device.number)"><input v-on:click="SendCode1($event)" name="Code" type="radio" :value="btn.value" />{{btn.name}}</label>
</div>
</div>
</form>
@ -553,7 +553,7 @@
<div class="card-header">
<h3 class="card-title">
<img src="~/images/serialport.png" />
{{device.DisplayName}}
{{device.displayName}}
</h3>
</div>
<div class="card-body">
@ -597,14 +597,14 @@
<div class="col-md-3 col-xs-6 control" v-for="device in GetDevices('一路开关')" :data-device-number="device.number">
<div class="card block2">
<div class="card-header">
<h3 class="card-title"><img src="~/images/switch1.png" />{{device.DisplayName||device.name}}</h3>
<h3 class="card-title"><img src="~/images/switch1.png" />{{device.displayName||device.name}}</h3>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="row" style="text-align:center;padding:3px 0;justify-content:center;">
<img v-if="GetDataValue(device.number,'L1状态')=='开'" v-on:click="CallApi(device.number,'/Switch/L1Off')" src="~/images/on.png" />
<img v-if="GetDataValue(device.number,'L1状态')=='关'" v-on:click="CallApi(device.number,'/Switch/L1On')" src="~/images/off.png" />
<img v-if="GetDataValue(device.number,'状态')=='开'" v-on:click="CallApi(device.number,'/Switch/L1Off')" src="~/images/on.png" />
<img v-if="GetDataValue(device.number,'状态')=='关'" v-on:click="CallApi(device.number,'/Switch/L1On')" src="~/images/off.png" />
</div>
</div>
</div>
@ -614,7 +614,7 @@
<div class="col-md-3 col-xs-6 control" v-for="device in GetDevices('二路开关')" :data-device-number="device.number">
<div class="card block2">
<div class="card-header">
<h3 class="card-title"><img src="~/images/switch2.png" />{{device.DisplayName||device.name}}</h3>
<h3 class="card-title"><img src="~/images/switch2.png" />{{device.displayName||device.name}}</h3>
<div class="card-tools">
<button class="btn btn-sm btn-success" v-on:click="CallApi(device.number,'/Switch3/On')" :data-node-number="model.number">一键开</button>
<button class="btn btn-sm btn-success" v-on:click="CallApi(device.number,'/Switch3/Off')" :data-node-number="model.number">一键关</button>
@ -637,7 +637,7 @@
<div class="col-md-3 col-xs-6 control" v-for="device in GetDevices('三路开关')" :data-device-number="device.number">
<div class="card block2">
<div class="card-header">
<h3 class="card-title"><img src="~/images/switch3.png" />{{device.DisplayName||device.name}}</h3>
<h3 class="card-title"><img src="~/images/switch3.png" />{{device.displayName||device.name}}</h3>
<div class="card-tools">
<button class="btn btn-sm btn-success" v-on:click="CallApi(device.number,'/Switch3/On')" :data-node-number="model.number">一键开</button>
<button class="btn btn-sm btn-success" v-on:click="CallApi(device.number,'/Switch3/Off')" :data-node-number="model.number">一键关</button>
@ -662,7 +662,7 @@
<div class="col-md-3 col-xs-6 control" v-for="device in GetDevices('插座')" :data-device-number="device.number">
<div class="card block2">
<div class="card-header">
<h3 class="card-title"><img src="~/images/socket.png" />{{device.DisplayName||device.name}}</h3>
<h3 class="card-title"><img src="~/images/socket.png" />{{device.displayName||device.name}}</h3>
</div>
<div class="card-body">
<div class="row">
@ -679,7 +679,7 @@
<div class="col-md-3 col-xs-6 control" v-for="device in GetDevices('智能插座')" :data-device-number="device.number">
<div class="card block2">
<div class="card-header">
<h3 class="card-title"><img src="~/images/socket.png" />{{device.DisplayName||device.name}}</h3>
<h3 class="card-title"><img src="~/images/socket.png" />{{device.displayName||device.name}}</h3>
<div class="card-tools">
{{parseFloat(GetDataValue(device.number,'电量')).toFixed(2)}} kWh
</div>
@ -699,7 +699,7 @@
<div class="col-md-3 col-xs-6 control" v-for="device in GetDevices('窗帘电机')" :data-device-number="device.number">
<div class="card block2">
<div class="card-header">
<h3 class="card-title"><img src="~/images/curtain.png" />{{device.DisplayName||device.name}}</h3>
<h3 class="card-title"><img src="~/images/curtain.png" />{{device.displayName||device.name}}</h3>
<div class="card-tools">
{{GetDataValue(device.number,'状态')}}
</div>
@ -723,7 +723,7 @@
<div class="card" style="height:306px;">
<div class="card-header">
<div class="card-title">
{{device.DisplayName}}
{{device.displayName}}
</div>
</div>
<div class="card-body">

@ -58,7 +58,7 @@ namespace IoTNode.Controllers
public IActionResult Logout()
{
HttpContext.Response.Cookies.Delete("jwt");
HttpContext.JwtSignOut();
//HttpContext.SignOutAsync();
return RedirectToAction("Index", "Home");
}
@ -95,7 +95,7 @@ namespace IoTNode.Controllers
{
if (user.PasswordHash == this._encryptionService.CreatePasswordHash(password, user.SecurityStamp))
{
HttpContext.SignIn(model.UserName, model.RememberMe, _cfg);
HttpContext.JwtSignIn(model.UserName, model.RememberMe, _cfg);
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
@ -295,14 +295,5 @@ namespace IoTNode.Controllers
}
#endregion Ajax验证
[Route("/login")]
[AllowAnonymous]
public IActionResult Test()
{
var userName = "super";
HttpContext.SignIn(userName, true, _cfg);
return RedirectToAction("Index", "Home");
}
}
}

@ -94,8 +94,7 @@ namespace UserCenter.Controllers
returnUrl = Url.Action("Index", "Home");
}
ViewBag.Url = returnUrl;
HttpContext.Response.Cookies.Delete("jwt");
HttpContext.SignOutAsync();
HttpContext.JwtSignOut();
return View("JsonpLogout", urls);
}
@ -205,7 +204,7 @@ namespace UserCenter.Controllers
}
else
{
HttpContext.SignIn(model.UserName, model.RememberMe, _cfg);
HttpContext.JwtSignIn(model.UserName, model.RememberMe, _cfg);
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
@ -219,6 +218,8 @@ namespace UserCenter.Controllers
var sign = string.Concat(userName, timestamp, site.Key).Md5();
var url = site.Login
.SetParam(nameof(username), username)
.SetParam(nameof(user.NickName), user.NickName)
.SetParam(nameof(user.Avatar), user.Avatar)
.SetParam(nameof(timestamp), timestamp)
.SetParam("rememberme", model.RememberMe)
.SetParam(nameof(sign), sign);

Loading…
Cancel
Save