feat: 短信验证码锁屏功能

This commit is contained in:
Argo Zhang 2019-09-17 12:52:14 +08:00
parent 80850165a6
commit 14ea70fae5
No known key found for this signature in database
GPG Key ID: 152E398953DDF19F
7 changed files with 132 additions and 29 deletions

View File

@ -24,6 +24,7 @@ namespace Bootstrap.Admin.Controllers
[AutoValidateAntiforgeryToken]
public class AccountController : Controller
{
private const string MobileSchema = "Mobile";
/// <summary>
/// 系统锁屏界面
/// </summary>
@ -33,10 +34,12 @@ namespace Bootstrap.Admin.Controllers
{
if (!User.Identity.IsAuthenticated) return Login();
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var authenticationType = User.Identity.AuthenticationType;
await HttpContext.SignOutAsync();
var urlReferrer = Request.Headers["Referer"].FirstOrDefault();
return View(new LockModel(this)
{
AuthenticationType = authenticationType,
ReturnUrl = WebUtility.UrlEncode(string.IsNullOrEmpty(urlReferrer) ? CookieAuthenticationDefaults.LoginPath.Value : urlReferrer)
});
}
@ -44,15 +47,20 @@ namespace Bootstrap.Admin.Controllers
/// <summary>
/// 系统锁屏界面
/// </summary>
/// <param name="configuration"></param>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="authType"></param>
/// <returns></returns>
[HttpPost]
[IgnoreAntiforgeryToken]
public Task<IActionResult> Lock(string userName, string password)
public Task<IActionResult> Lock([FromServices]IConfiguration configuration, string userName, string password, string authType)
{
// 根据不同的登陆方式
return Login(userName, password, string.Empty);
Task<IActionResult> ret;
if (authType == MobileSchema) ret = Mobile(configuration, userName, password);
else ret = Login(userName, password, string.Empty);
return ret;
}
/// <summary>
@ -73,7 +81,6 @@ namespace Bootstrap.Admin.Controllers
/// <summary>
/// 短信验证登陆方法
/// </summary>
/// <param name="ipLocator"></param>
/// <param name="configuration"></param>
/// <param name="phone"></param>
/// <param name="code"></param>
@ -107,7 +114,7 @@ namespace Bootstrap.Admin.Controllers
RoleHelper.SaveByUserId(user.Id, roles);
}
}
return auth ? await SignInAsync(phone, true) : View("Login", new LoginModel() { AuthFailed = true });
return auth ? await SignInAsync(phone, true, MobileSchema) : View("Login", new LoginModel() { AuthFailed = true });
}
/// <summary>
@ -125,9 +132,9 @@ namespace Bootstrap.Admin.Controllers
return auth ? await SignInAsync(userName, remember == "true") : View("Login", new LoginModel() { AuthFailed = true });
}
private async Task<IActionResult> SignInAsync(string userName, bool persistent)
private async Task<IActionResult> SignInAsync(string userName, bool persistent, string authenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme)
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
var identity = new ClaimsIdentity(authenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { ExpiresUtc = DateTimeOffset.Now.AddDays(DictHelper.RetrieveCookieExpiresPeriod()), IsPersistent = persistent });

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace Bootstrap.Admin.Models
{
@ -20,5 +20,10 @@ namespace Bootstrap.Admin.Models
/// 获得/设置 返回路径
/// </summary>
public string ReturnUrl { get; set; }
/// <summary>
/// 获得/设置 认证方式 Cookie Mobile Gitee GitHub
/// </summary>
public string AuthenticationType { get; set; }
}
}

View File

@ -30,8 +30,7 @@
<img alt="lock avatar" src="@Url.Content(Model.Icon)" />
<h1>@Model.DisplayName</h1>
<span class="locked">系统已锁定</span>
<form role="form" class="form-inline justify-content-center" method="post" autocomplete="off" action="~/Account/Lock?ReturnUrl=@Model.ReturnUrl">
<input type="hidden" name="username" value="@Model.UserName" />
<form role="form" class="form-inline justify-content-center @Model.AuthenticationType" method="post" autocomplete="off" action="?ReturnUrl=@Model.ReturnUrl">
<div class="form-group">
<div class="input-group">
<input type="password" name="password" class="form-control" value="" autocomplete="off" placeholder="密码" />
@ -42,6 +41,21 @@
</div>
</div>
</div>
<input type="hidden" name="username" value="@Model.UserName" />
<input type="hidden" name="authType" value="@Model.AuthenticationType" />
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">
<span class="fa fa-lock"></span>
</div>
</div>
<input type="text" id="smscode" class="form-control" data-toggle="tooltip" disabled value="" placeholder="验证码" maxlength="4" title="请输入验证码" />
<div class="input-group-append">
<button type="button" id="btnSendCode" class="btn btn-lock btn-sms" data-method="send" data-toggle="tooltip" title="点击发送验证码">发送验证码</button>
</div>
</div>
</div>
</form>
</div>
</div>

View File

@ -84,30 +84,51 @@ body {
border-color: #3c763d;
}
div.input-group span {
top: 0;
background: #02b5c2;
border-color: #2e6da4;
color: #fff;
}
.form-inline .input-group input:focus {
z-index: auto;
}
div.input-group input, div.input-group input:hover, .btn-lock {
.lock-box .form-inline .form-group {
display: none;
}
.lock-box .form-inline.Cookies .form-group:first-child {
display: flex;
}
.lock-box .form-inline.Mobile .form-group:last-child {
display: flex;
}
div.input-group span {
color: #fff;
}
div.input-group input, div.input-group input:hover, .btn-lock, div.input-group .input-group-text {
border-color: #1d9238;
}
div.input-group input:focus {
box-shadow: none;
div.input-group input:focus {
box-shadow: none;
}
div.input-group input, div.input-group input:hover, div.input-group input:focus {
border-right: none;
}
div.input-group input.error {
background-color: #dcc4c4;
border-color: #e21717;
}
div.input-group .input-group-text {
background-color: #02b5c2;
}
div.input-group input, div.input-group input:hover, div.input-group input:focus {
border-right: none;
.btn-sms {
width: 122px;
}
div.input-group input.error {
background-color: #dcc4c4;
border-color: #e21717;
}
.form-group:last-child input {
width: 80px;
}

View File

@ -1,4 +1,4 @@
$(function () {
$(function () {
$('#time').text((new Date()).format('HH:mm:ss'));
setInterval(function () {
@ -6,4 +6,60 @@ $(function () {
}, 500);
$(".lock-wrapper").autoCenter();
var timeHanlder = null;
$('#btnSendCode').on('click', function () {
var $this = $(this);
var method = $this.attr('data-method');
var phone = $('input[name="username"]').val();
var $password = $('input[name="password"]');
var $code = $('#smscode');
var code = $code.val();
if (method === 'submit') {
if ($code.val() === '') {
$code.tooltip('show');
var handler = setTimeout(function () {
clearTimeout(handler);
$code.tooltip('hide');
}, 1000);
return true;
}
// 提交
$password.val(code);
$('form').submit();
return true;
}
// validate mobile phone
var apiUrl = "api/Login?phone=" + phone;
$.bc({
url: apiUrl,
method: 'PUT',
callback: function (result) {
$this.attr('data-original-title', result ? "发送成功" : "发送失败").tooltip('show');
var handler = setTimeout(function () {
clearTimeout(handler);
$this.tooltip('hide').tooltip('disable');
}, 1000);
if (result) {
// send success
$('#smscode').removeAttr('disabled');
$this.text('已发送').attr('data-method', 'submit');
timeHanlder = setTimeout(function () {
clearTimeout(timeHanlder);
var count = 299;
timeHanlder = setInterval(function () {
if (count === 0) {
clearInterval(timeHanlder);
$this.text('发送验证码').attr('data-method', 'send').attr('data-original-title', "点击发送验证码").tooltip('enable');
return;
}
$this.text('登录 (' + count-- + 's)');
}, 1000);
}, 1000);
}
}
});
});
});

View File

@ -190,7 +190,7 @@
var handler = setTimeout(function () {
clearTimeout(handler);
$this.tooltip('hide').attr('data-original-title', "点击发送验证码");
}, 1500);
}, 1000);
if (result) {
// send success

View File

@ -36,7 +36,7 @@ namespace Bootstrap.DataAccess
City = ipLocator.Locate(ip),
Browser = $"{agent.Browser?.Name} {agent.Browser?.Version}",
OS = $"{agent.OS?.Name} {agent.OS?.Version}",
Result = auth ? "登成功" : "登录失败"
Result = auth ? "登成功" : "登录失败"
};
return DbContextManager.Create<LoginUser>().Log(loginUser);
}