因项目需求需要一个功能
安全功能检测的系统缺陷:(用户登录系统后,执行系统敏感的操作(交易,涉及个人隐私信息的操作等),系统应对用户进行重新鉴别。)
如下图编辑用户属于系统敏感操作,当用户进行保存的时候需要弹窗一个请重新输入密码的提示框,然后输入密码进行校验(根据密码调用后台检测密码的接口然后进行判断是否有对应权限执行敏感操作),如果校验成功修改用户成功否则提示校验失败用户不能进行保存。
使用bootstrap的拟态弹窗可以轻易实现该功能,如下图
代码如下
<html>
<head>
<meta charset="UTF-8">
<title>Bootstrap拟态弹窗</title>
<link rel="stylesheet"
href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function() {
$("#check").click(function() {
var userLockedTime = $("[name='userLockedTime']").val();
var userLoginFailCount = $("[name='userLoginFailCount']").val();
var maximumOnline = $("[name='maximumOnline']").val();
var passwordRepeatTimes = $("[name='passwordRepeatTimes']").val();
var userLfetime = $("[name='userLfetime']").val();
var tempUserTime = $("[name='tempUserTime']").val();
var userSleep = $("[name='userSleep']").val();
var noLoginTime = $("[name='noLoginTime']").val();
var adminLogSize = $("[name='adminLogSize']").val();
console.log(userLockedTime+":"+userLoginFailCount+":"+passwordRepeatTimes);
if (userLockedTime != null && userLockedTime != "") {
if (!(/(^[0-9]{1,6}$)/.test(userLockedTime))) {
alert("用户锁定时间输入格式错误,请输入六位以内正整数。");
return false;
}
if (userLockedTime < 20) {
alert("用户锁定时间不能小于20分钟");
return false;
}
}
if (maximumOnline != null && maximumOnline != "") {
if (!(/(^[0-9]{1,6}$)/.test(maximumOnline))) {
alert("用户在线人数格式错误,请输入六位以内正整数。");
return false;
}
if (maximumOnline < 1) {
alert("用户最大上线人数不能小于1个");
return false;
}
}
if (userLoginFailCount != null && userLoginFailCount != "") {
if (!(/(^[0-9]{1,2}$)/.test(userLoginFailCount))) {
alert("用户登录失败次数输入格式错误,请输入两位以内正整数。");
return false;
}
if (userLoginFailCount > 10 || userLoginFailCount < 0) {
alert("用户登录失败次数锁定在1-10之间");
return false;
}
}
if (tempUserTime != null && tempUserTime != "") {
if (!(/(^[0-9]{1,2}$)/.test(tempUserTime))) {
alert("临时用户超时时间转为休眠输入格式错误,请输入两位位以内正整数。");
return false;
}
if (tempUserTime <= 0 || tempUserTime>90) {
alert("临时用户超时时间转为休眠(设置范围:1-90天)");
return false;
}
}
if (userSleep != null && userSleep != "") {
if (!(/(^[0-9]{1,3}$)/.test(userSleep))) {
alert("休眠用户超过时间转为注销输入格式错误,请输入三位以内正整数。");
return false;
}
if (userSleep < 30 || userSleep>365) {
alert("休眠用户超过时间转为注销(设置范围:30-365天)");
return false;
}
}
if (noLoginTime != null && noLoginTime != "") {
if (!(/(^[0-9]{1,3}$)/.test(noLoginTime))) {
alert("用户超时时间未登陆转为休眠输入格式错误,请输入三位位以内正整数。");
return false;
}
if (noLoginTime < 90 || noLoginTime>365) {
alert("用户超时时间未登陆转为休眠(设置范围:90-365天)");
return false;
}
}
if (passwordRepeatTimes != null && passwordRepeatTimes != "") {
if (!(/(^[0-9]{1,2}$)/.test(passwordRepeatTimes))) {
alert("用户密码最近重复次数输入格式错误,请输入两位位以内正整数。");
return false;
}
if (passwordRepeatTimes <= 0 ) {
alert("用户密码最近重复次数不能小于1");
return false;
}
}
if (adminLogSize != null && adminLogSize != "") {
if (!(/(^[0-9]{1,2}$)/.test(adminLogSize))) {
alert("管理员存储日志上限输入格式错误,请输入两位以内正整数。");
return false;
}
if (adminLogSize <= 0 ) {
alert("管理员存储日志上限不能小于1Gb");
return false;
}
}
if (userLfetime != null && userLfetime != "") {
if (userLfetime < 1 || userLfetime > 30) {
alert("用户锁定时间不能小于1分钟或者超过30分钟");
return false;
}
}
$("#show").trigger("click");
$("#vPwd").val("");
return true;
});
$("#modifySystemProperties").submit(function() {
var vStatus = false;
var vPwd = $("#vPwd").val();
if(vPwd=="123"){
vStatus = true;
alert("校验成功");
}else{
$('#close').trigger("click");
alert("校验失败");
}
//调用对应检测密码的接口
//if(vPwd!=null){
// $.ajax({
// type : "POST",
// url : "${path}/user_verificationPassword.action",
// async : false,
// data : {
// "password" : $("#vPwd").val()
// },
// success:function(res){
// if(res=="success"){
// alert("校验成功");
// vStatus = true;
// }else{
// $('#close').trigger("click");
// alert("校验失败");
// }
// }
// });
//}
return vStatus;
});
})
</script>
<style type="text/css">
.top{
margin-top:30px
}
</style>
</head>
<body>
<div class="">
<form id="modifySystemProperties"
action="">
<table class="" style="margin-left: 20px; width:696px"
border="0">
<tr>
<td>
<div class="top"></div>
用户锁定时间:<input name="userLockedTime" type="text" />(用户锁定时间(最少20分钟))
</td>
</tr>
<tr>
<td><div class="top"></div>最大上线人数:<input name="maximumOnline" type="text" />(最大上线人数(最少1个))
</td>
</tr>
<tr>
<td><div class="top"></div>用户登录失败次数锁定<input name="userLoginFailCount" type="text" />(用户失败多少次后进行锁定(1-10次))
</td>
</tr>
<tr>
<td><div class="top"></div>用户密码最近重复次数<input name="passwordRepeatTimes" type="text" />(密码重复次数,不能和前几次密码重复,最少为1)
</td>
</tr>
<tr>
<td><div class="top"></div>用户会话超时时间设置<input name="userLfetime" type="text" />(用户存活时间(时间1-30分钟))
</td>
</tr>
<!--<tr> <td>
临时用户超时时间转为休眠设置<input name="tempUserTime" type="text" />(设置范围:1-90天)
</td>
</tr>
<tr>
<td>
休眠用户超过时间转为注销设置<input name="userSleep" type="text" />(设置范围:30-365天)
</td>
</tr>
<tr>
<td>
用户超时时间未登陆转为休眠设置<input name="noLoginTime" type="text" />(设置范围:90-365天)
</td></tr> -->
<tr>
<td><div class="top"></div>管理员存储日志上限设置<input name="adminLogSize" type="text" />(上限最少1gb,单位是gb)
</td>
</tr>
<tr>
<td><div class="top"></div><input id="check" type="button" class="btn btn-primary" value="配置修改" />
<input type="hidden" id="show" data-toggle="modal" data-target="#myModal"/>
</td>
</tr>
</table>
<!-- 模态框(Modal) -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">请输入密码进行身份校验</h4>
</div>
<div class="modal-body">
<input id="vPwd" type="password" class="form-control" />
</div>
<div class="modal-footer">
<button type="button" id="close" class="btn btn-default"
data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
Bootstrap确实很容易就实现了对应的功能,但是坑爹的是开发的项目jquery版本没有控制好(项目不想多说什么什么乱七八糟的东西都有,然后这个项目又是基于二次开发所以不敢乱动啥),导致导入bootstrap的拟态弹窗失效(心里一万个草泥马崩腾而过,我一java开发容易吗我,害啥也不是)。
然后就想其他的方法进行补救,想到了js原生的自定义弹窗特效,立马就打开我的宝贝百度搜索(js自定义弹窗)果然有对应的实现,我就立马开启了CV大法,新建demo.html复制代码粘贴,还好在跑页面的时候心里默念了阿弥陀佛,一跑就通。
引用了山海之间这个大佬的自定义弹窗实现,他的博客园链接
https://www.cnblogs.com/websharehome/p/9438741.html
我在他的基础上根据我的需求进行了小部分的改动,终于实现了我要的功能(长叹一口气),如下图
demo代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>自定义弹窗</title>
<link rel="stylesheet" href="alert.css">
<style type="text/css">
/* 弹出框最外层 */
.msg__wrap {
position: fixed;
top: 50%;
left: 50%;
z-index: 10;
transition: all .3s;
transform: translate(-50%, -50%) scale(0, 0);
max-width: 50%;
background: #fff;
box-shadow: 0 0 10px #eee;
font-size: 10px;
}
/* 弹出框头部 */
.msg__wrap .msg-header {
padding: 10px 10px 0 10px;
font-size: 1.8em;
}
.msg__wrap .msg-header .msg-header-close-button {
float: right;
cursor: pointer;
}
/* 弹出框中部 */
.msg__wrap .msg-body {
padding: 10px 10px 10px 10px;
display: flex;
}
/* 图标 */
.msg__wrap .msg-body .msg-body-icon{
width: 80px;
}
.msg__wrap .msg-body .msg-body-icon div{
width: 45px;
height: 45px;
margin: 0 auto;
line-height: 45px;
color: #fff;
border-radius: 50% 50%;
font-size: 2em;
}
.msg__wrap .msg-body .msg-body-icon .msg-body-icon-success{
background: #32a323;
text-align: center;
}
.msg__wrap .msg-body .msg-body-icon .msg-body-icon-success::after{
content: "成";
}
.msg__wrap .msg-body .msg-body-icon .msg-body-icon-wrong{
background: #ff8080;
text-align: center;
}
.msg__wrap .msg-body .msg-body-icon .msg-body-icon-wrong::after{
content: "误";
}
.msg__wrap .msg-body .msg-body-icon .msg-body-icon-info{
background: #80b7ff;
text-align: center;
}
.msg__wrap .msg-body .msg-body-icon .msg-body-icon-info::after{
content: "注";
}
/* 内容 */
.msg__wrap .msg-body .msg-body-content{
min-width: 200px;
font-size: 1.5em;
word-break: break-all;
display: flex;
align-items: center;
padding-left: 10px;
box-sizing: border-box;
}
/* 弹出框底部 */
.msg__wrap .msg-footer {
padding: 0 10px 10px 10px;
display: flex;
flex-direction: row-reverse;
}
.msg__wrap .msg-footer .msg-footer-btn {
width: 50px;
height: 30px;
border: 0 none;
color: #fff;
outline: none;
font-size: 1em;
border-radius: 2px;
margin-left: 5px;
cursor: pointer;
}
.msg__wrap .msg-footer .msg-footer-cancel-button{
background-color: #ff3b3b;
}
.msg__wrap .msg-footer .msg-footer-cancel-button:active{
background-color: #ff6f6f;
}
.msg__wrap .msg-footer .msg-footer-confirm-button{
background-color: #4896f0;
}
.msg__wrap .msg-footer .msg-footer-confirm-button:active{
background-color: #1d5fac;
}
/* 遮罩层 */
.msg__overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 5;
background-color: rgba(0, 0, 0, .4);
transition: all .3s;
opacity: 0;
}
</style>
<script type="text/javascript">
/*
*自定义弹窗
*/
//自执行函数 形成封闭的作用域 避免全局污染
//传入windwo和document对象 相当于将window和document作为了作用域中的局部变量,
//就不需要内部函数沿着作用域链再查找到最顶层的window 提高运行效率。
(function (window, document) {
//定义一个构造函数Msg 作为弹窗实例的构造函数。
let Msg = function (options) {
//执行初始化操作
this._init(options);
}
//定义初始化方法 并对方法传递的参数进行初始化
Msg.prototype = {
_init({
content = "", //文本内容
type = "info", //信息类型
useHTML = false, //是否解析html字符串
showIcon = true, //是否展示弹窗图标
confirm = null, //确认后得回调
cancle = null, //取消后得回调
footer = true, //是否显示底部的确认按钮
header = true, //是否显示头部信息及关闭按钮
title = "请输入密码进行校验", //弹窗标题
contentStyle = {}, //内容样式
contentFontSize = "1.5em", //内容字体大小
btnName = ["确定", "取消"] //按钮文字内容
}) {
//将传入的值绑定到this上
this.content = content;
this.type = type;
this.useHTML = useHTML;
this.showIcon = showIcon;
this.confirm = confirm;
this.cancle = cancle;
this.footer = footer;
this.header = header;
this.title = title;
this.contentStyle = contentStyle;
this.contentFontSize = contentFontSize;
this.btnName = btnName;
//执行创建元素方法
this._creatElement();
//显示弹窗及遮罩
this._show({
el: this._el,
overlay: this._overlay
});
//绑定事件处理函数
this._bind({
el: this._el,
overlay: this._overlay
});
},
//创建弹窗元素方法
_creatElement() {
//创建最外层得包裹元素
let wrap = document.createElement("div");
wrap.className = "msg__wrap";
//定义弹窗得两个按钮
const [confirmBtnName, cancelBtnName] = this.btnName;
//判断是否显示弹窗标题
const headerHTML = this.header ?
`
${this.title}
` : "";
//判断是否显示图标
const iconHTML = this.showIcon ?
` ` : "";
//判断是否显示弹窗底部按钮
const footerHTML = this.footer ?
` ` : "";
//拼接完整html
const innerHTML = `${headerHTML}
${iconHTML}
${footerHTML}`;
//将拼接的html赋值到wrap中
wrap.innerHTML = innerHTML;
//把自定义的样式进行合并
const contentStyle = {
fontSize: this.contentFontSize,
...this.contentStyle
}
//获取内容所属DOM
let content = wrap.querySelector(".msg-body .msg-body-content");
//将传过来的样式添加到contentDOM
for (const key in contentStyle) {
if (contentStyle.hasOwnProperty(key)) {
content.style[key] = contentStyle[key];
}
}
//给弹窗的conntent赋值
if (this.useHTML) {
content.innerHTML = ``;
} else {
content.innerHTML = ``;
// content.innerText = this.content;
}
//创建遮罩层
let overlay = document.createElement("div");
overlay.className = "msg__overlay";
//把dom挂载到当前实例上
this._overlay = overlay;
this._el = wrap;
},
//弹窗展现方法
_show({
el,
overlay
}) {
//把弹窗的dom和遮罩插入到页面中
document.body.appendChild(el);
document.body.appendChild(overlay);
//将弹窗显示出来 timeout进行异步处理显示动画
setTimeout(() => {
el.style.transform = "translate(-50%,-50%) scale(1,1)";
overlay.style.opacity = "1";
})
},
//关闭弹窗方法
_close({
el,
overlay
}) {
//隐藏dom
el.style.transform = "translate(-50%,-50%) scale(0,0)";
overlay.style.opcity = "0";
//根据动画时间 动画完成再移除
setTimeout(() => {
//把弹窗的dom和遮罩移除
document.body.removeChild(el)
document.body.removeChild(overlay);
}, 300);
},
//事件处理函数,为DOM绑定事件
_bind({
el,
overlay
}) {
//保存当前this
//const _this = this;
const cancle = (e) => {
this.cancle && this.cancle.call(this, e);
//隐藏弹窗
//hideMsg();
this._close({
el,
overlay
});
}
//确认弹窗
const confirm = (e) => {
this.confirm && this.confirm.call(this, e);
this._close({
el,
overlay
});
}
//顶部关闭按钮绑定事件
if (this.header) {
el.querySelector(".msg-header-close-button").addEventListener("click", cancle);
}
//弹窗底部两个按钮事件监听
if (this.footer) {
el.querySelector(".msg-footer-cancel-button").addEventListener("click", cancle);
el.querySelector(".msg-footer-confirm-button").addEventListener("click", confirm)
}
}
}
//将构造函数暴露到window 可直接在全局作用域中访问构造函数
window.$Msg = Msg;
})(window, document);
</script>
</head>
<body>
<button>Click me</button>
<script src="index.js"></script>
<script>
document.querySelector("button").addEventListener("click",()=>{
new $Msg({
content:"我的自定义弹窗好了",
type:"success",
cancle:function(){
alert("关闭");
},
confirm:function(){
var a = document.getElementById("vPwd").value;//对应密码
if(a == "123"){
alert("校验成功");
}else{
alert("校验失败");
}
}
})
})
</script>
</body>
</html>
然后就根据这个demo对项目进行改造,结果又有坑哭了
bug如下
乱码????
吓得我立马去查项目是不是utf8格式,和对应的js是不是utf8格式
都是utf-8那怎么可能会乱码呢???我真的是对前端绝望了,然后打开前端的控制台看响应的文件
我果断通过前台的控制台复制对应的js地址直接进行访问
还是乱码,网上查了一大堆js乱码咋办的教程,各种方式结果都解决不了。。。,
我砸电脑的心都有了,在我打算放弃了的时候,我突然灵光一现,我就试试utf8他兄弟utf8-bom看看那还会不会乱码,结果奇迹般被我瞎猫碰到死耗子解决了我。。。
编程真的非常玄学尤其是前端唉。
解决如下,使用notepad++把对应的js转换格式为utf8 bom
替换项目里对应的js,utf8那个格式什么的全部都不用改直接继续访问对应的js文件
不乱码了,果断项目跑通直接去试我的功能
成功了
唉,前端是真的坑爹啊,为什么java程序员要写前端呢
写这篇博客就是防止各位刚入行的同行别犯我这个错,踩了一个大大的坑。