验证码改为滑块

hangao-new
wangxy 1 year ago
parent b3b0177027
commit a2df444072

@ -145,3 +145,17 @@ xss:
swagger:
# 是否开启swagger
enabled: false
# 滑块验证码
aj:
captcha:
# blockPuzzle滑块 clickWord文字点选 default默认两者都实例化
type: blockPuzzle
# 右下角显示字
water-mark:
# 校验滑动拼图允许误差偏移量(默认5像素)
slip-offset: 5
# aes加密坐标开启或者禁用(true|false)
aes-status: true
# 滑动干扰项(0/1/2)
interference-options: 0

@ -0,0 +1,12 @@
// 加密数据函数 工具crypto.js 文件工具
/**
* @word 要加密的内容
* @keyWord String 服务器随机返回的关键字
* */
function aesEncrypt(word,keyWord){
// var keyWord = keyWord || "XwKsGlMcdPMEhR1B"
var key = CryptoJS.enc.Utf8.parse(keyWord);
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}

@ -0,0 +1 @@
function aesEncrypt(d,e){var a=CryptoJS.enc.Utf8.parse(e);var c=CryptoJS.enc.Utf8.parse(d);var b=CryptoJS.AES.encrypt(c,a,{mode:CryptoJS.mode.ECB,padding:CryptoJS.pad.Pkcs7});return b.toString()};

File diff suppressed because one or more lines are too long

@ -0,0 +1,275 @@
.verify-code {
font-size: 20px;
text-align: center;
cursor: pointer;
margin-bottom: 5px;
border: 1px solid #ddd;
}
.cerify-code-panel {
height:100%;
overflow:hidden;
}
.verify-code-area {
float:left;
}
.verify-input-area {
float: left;
width: 60%;
padding-right: 10px;
}
.verify-change-area {
line-height: 30px;
float: left;
}
.varify-input-code {
display:inline-block;
width: 100%;
height: 25px;
}
.verify-change-code {
color: #337AB7;
cursor: pointer;
}
.verify-btn {
width: 200px;
height: 30px;
background-color: #337AB7;
color:#FFFFFF;
border:none;
margin-top: 10px;
}
.verifybox{
position: relative;
box-sizing: border-box;
border-radius: 2px;
border: 1px solid #e4e7eb;
background-color: #fff;
box-shadow: 0 0 10px rgba(0,0,0,.3);
left: 50%;
top:50%;
transform: translate(-50%,-50%);
}
.verifybox-top{
padding: 0 15px;
height: 40px;
line-height: 40px;
text-align: left;
font-size: 16px;
color: #45494c;
border-bottom: 1px solid #e4e7eb;
box-sizing: border-box;
}
.verifybox-bottom{
padding: 15px;
box-sizing: border-box;
}
.verifybox-close{
position: absolute;
top: 8px;
right: 9px;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
cursor: pointer;
transition: transform 0.2s ease;
}
.verifybox-close .icon-close{
font-weight: bold;
}
.verifybox-close:hover {
transition: transform 0.2s ease;
transform:rotate(60deg);
-ms-transform:rotate(60deg);
-moz-transform:rotate(60deg);
-webkit-transform:rotate(60deg);
-o-transform:rotate(60deg);
}
.mask{
position: fixed;
top: 0;
left:0;
z-index: 1001;
width: 100%;
height: 100vh;
background: rgba(0,0,0,.3);
/* display: none; */
transition: all .5s;
display: none;
}
.verify-tips{
position: absolute;
display: none;
left: 0px;
bottom:-35px;
width: 100%;
height: 30px;
/* transition: all .5s; */
line-height:30px;
color: #fff;
/* animation:move 1.5s linear; */
}
@keyframes move {
0%{
bottom:-35px;
}
50%,80%{
bottom:0px;
}
100%{
bottom:-35px;
}
}
.suc-bg{
background-color:rgba(92, 184, 92,.5);
filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7f5CB85C, endcolorstr=#7f5CB85C);
}
.err-bg{
background-color:rgba(217, 83, 79,.5);
filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7fD9534F, endcolorstr=#7fD9534F);
}
/*滑动验证码*/
.verify-bar-area {
position: relative;
background: #FFFFFF;
text-align: center;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
border: 1px solid #ddd;
-webkit-border-radius: 4px;
}
.verify-bar-area .verify-move-block {
position: absolute;
top: 0px;
left: 0;
background: #fff;
cursor: move;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
box-shadow: 0 0 2px #888888;
-webkit-border-radius: 1px;
}
.verify-bar-area .verify-move-block:hover {
background-color: #337ab7;
color: #FFFFFF;
}
.verify-bar-area .verify-left-bar {
position: absolute;
top: -1px;
left: -1px;
background: #f0fff0;
cursor: pointer;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
border: 1px solid #ddd;
}
.verify-img-panel {
margin:0;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
border: 1px solid #ddd;
border-radius: 3px;
position: relative;
}
/*.verify-img-panel .verify-refresh {*/
/* width: 25px;*/
/* height: 25px;*/
/* text-align:center;*/
/* padding: 5px;*/
/* cursor: pointer;*/
/* position: absolute;*/
/* top: 0;*/
/* right: 0;*/
/* z-index: 2;*/
/*}*/
.verify-img-panel .verify-refresh img {
pointer-events: auto;
display: block;
width: 30px;
height: 30px;
position: absolute;
top: 10px;
right: 10px;
transition: 200ms;
cursor: pointer;
}
.verify-img-panel .icon-refresh {
font-size: 20px;
color: #fff;
}
.verify-img-panel .verify-gap {
background-color: #fff;
position: relative;
z-index: 2;
border:1px solid #fff;
}
.verify-bar-area .verify-move-block .verify-sub-block {
position: absolute;
text-align: center;
z-index: 3;
/* border: 1px solid #fff; */
}
.verify-bar-area .verify-move-block .verify-icon {
font-size: 18px;
}
.verify-bar-area .verify-msg {
z-index : 3;
font-weight: 700;
color: #40485b;
}
/*字体图标的css*/
@font-face {font-family: "iconfont";
src: url('../fonts/iconfont.eot?t=1508229193188'); /* IE9*/
src: url('../fonts/iconfont.eot?t=1508229193188#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('../fonts/iconfont.ttf?t=1508229193188') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('../fonts/iconfont.svg?t=1508229193188#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-check:before { content: "\e645"; }
.icon-close:before { content: "\e646"; }
.icon-right:before { content: "\e6a3"; }
.icon-refresh:before { content: "\e6a4"; }

File diff suppressed because one or more lines are too long

@ -0,0 +1,45 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
<glyph glyph-name="check" unicode="&#58949;" d="M887.904 597.792c-12.864 12.064-33.152 11.488-45.216-1.408L415.936 142.016l-233.12 229.696C170.208 384.128 149.952 384 137.536 371.392c-12.416-12.576-12.256-32.864 0.352-45.248l256.48-252.672c0.096-0.096 0.224-0.128 0.32-0.224 0.096-0.096 0.128-0.224 0.224-0.32 2.016-1.92 4.448-3.008 6.784-4.288 1.152-0.672 2.144-1.664 3.36-2.144 3.776-1.472 7.776-2.24 11.744-2.24 4.192 0 8.384 0.832 12.288 2.496 1.312 0.544 2.336 1.664 3.552 2.368 2.4 1.408 4.896 2.592 6.944 4.672 0.096 0.096 0.128 0.256 0.224 0.352 0.064 0.096 0.192 0.128 0.288 0.224l449.184 478.208C901.44 565.408 900.768 585.664 887.904 597.792z" horiz-adv-x="1024" />
<glyph glyph-name="close" unicode="&#58950;" d="M557.312 382.752l265.28 263.904c12.544 12.48 12.608 32.704 0.128 45.248-12.512 12.576-32.704 12.608-45.248 0.128l-265.344-263.936-263.04 263.84C236.64 704.416 216.384 704.48 203.84 692 191.328 679.52 191.296 659.264 203.776 646.72l262.976-263.776L201.6 119.2c-12.544-12.48-12.608-32.704-0.128-45.248 6.24-6.272 14.464-9.44 22.688-9.44 8.16 0 16.32 3.104 22.56 9.312l265.216 263.808 265.44-266.24c6.24-6.272 14.432-9.408 22.656-9.408 8.192 0 16.352 3.136 22.592 9.344 12.512 12.48 12.544 32.704 0.064 45.248L557.312 382.752z" horiz-adv-x="1024" />
<glyph glyph-name="right" unicode="&#59043;" d="M761.056 363.872c0.512 0.992 1.344 1.824 1.792 2.848 8.8 18.304 5.92 40.704-9.664 55.424L399.936 756.256c-19.264 18.208-49.632 17.344-67.872-1.888-18.208-19.264-17.376-49.632 1.888-67.872l316.96-299.84-315.712-304.288c-19.072-18.4-19.648-48.768-1.248-67.872 9.408-9.792 21.984-14.688 34.56-14.688 12 0 24 4.48 33.312 13.44l350.048 337.376c0.672 0.672 0.928 1.6 1.6 2.304 0.512 0.48 1.056 0.832 1.568 1.344C757.76 357.12 759.2 360.608 761.056 363.872z" horiz-adv-x="1024" />
<glyph glyph-name="refresh" unicode="&#59044;" d="M939.456 639.776c-16.672 5.984-34.976-2.72-40.896-19.36l-24.768-69.344c-28.992 65.312-74.784 122.72-133.088 165.92C555.328 854.272 291.296 816.768 152.32 633.344c-67.264-88.768-95.616-198.176-79.84-308.032 15.84-110.304 74.208-207.776 164.352-274.496 75.424-55.808 163.808-82.752 251.456-82.752 128.032 0 254.56 57.44 336.992 166.272 36.48 48.128 61.472 102.08 74.208 160.416 3.776 17.248-7.136 34.304-24.416 38.08-17.216 3.712-34.304-7.104-38.08-24.416-10.784-49.184-31.872-94.752-62.72-135.456-117.888-155.52-341.92-187.232-499.392-70.72-76.288 56.48-125.664 138.912-139.072 232.16-13.344 92.8 10.656 185.248 67.488 260.288 117.856 155.584 341.792 187.424 499.328 70.848 57.024-42.24 99.84-100.608 122.976-166.624l-109.984 42.944c-16.416 6.368-35.008-1.696-41.44-18.176-6.432-16.48 1.728-35.008 18.176-41.44l161.856-63.2c3.808-1.472 7.744-2.208 11.616-2.208 0.544 0 1.024 0.192 1.568 0.224 1.216-0.128 2.432-0.64 3.648-0.64 13.12 0 25.472 8.16 30.112 21.248l57.632 161.184C964.768 615.52 956.096 633.856 939.456 639.776z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@ -0,0 +1,705 @@
/*! Verify&admin MIT License by anji-plus*/
;(function($, window, document,undefined) {
// 初始话 uuid
uuid()
function uuid() {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
var slider = 'slider'+ '-'+s.join("");
var point = 'point'+ '-'+s.join("");
if(!localStorage.getItem('slider')) {
localStorage.setItem('slider', slider)
}
if(!localStorage.getItem('point')) {
localStorage.setItem("point",point);
}
}
var startX,startY;
document.addEventListener("touchstart",function(e){
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;
});
document.addEventListener("touchmove",function(e){
var moveX = e.targetTouches[0].pageX;
var moveY = e.targetTouches[0].pageY;
if(Math.abs(moveX-startX)>Math.abs(moveY-startY)){
e.preventDefault();
}
},{passive:false});
//请求图片get事件
function getPictrue(data,baseUrl,resolve,reject){
$.ajax({
type : "post",
contentType: "application/json;charset=UTF-8",
url : baseUrl + "captcha/get",
data :JSON.stringify(data),
cache: false,
crossDomain: true == !(document.all),
success:function(res){
resolve(res)
},
fail: function(err) {
reject(err)
}
})
}
//验证图片check事件
function checkPictrue(data,baseUrl,resolve,reject){
$.ajax({
type : "post",
contentType: "application/json;charset=UTF-8",
url : baseUrl + "captcha/check",
data :JSON.stringify(data),
cache: false,
crossDomain: true == !(document.all),
success:function(res){
resolve(res)
},
fail: function(err) {
reject(err)
}
})
}
//定义Slide的构造函数
var Slide = function(ele, opt) {
this.$element = ele,
this.backToken = null,
this.moveLeftDistance = 0,
this.secretKey = '',
this.defaults = {
baseUrl:"https://captcha.anji-plus.com/captcha-api",
containerId:'',
captchaType:"blockPuzzle",
mode : 'fixed', //弹出式pop固定fixed
vOffset: 5,
vSpace : 5,
explain : '向右滑动完成验证',
imgSize : {
width: '360px',
height: '155px',
},
blockSize : {
width: '50px',
height: '50px',
},
circleRadius: '10px',
barSize : {
width : '360px',
height : '40px',
},
beforeCheck:function(){ return true},
ready : function(){},
success : function(){},
error : function(){}
},
this.options = $.extend({}, this.defaults, opt)
};
//定义Slide的方法
Slide.prototype = {
init: function() {
var _this = this;
//加载页面
this.loadDom();
_this.refresh();
this.options.ready();
this.$element[0].onselectstart = document.body.ondrag = function(){
return false;
};
if(this.options.mode == 'pop') {
_this.$element.find('.verifybox-close').on('click', function() {
_this.$element.find(".mask").css("display","none");
_this.refresh();
});
var clickBtn = document.getElementById(this.options.containerId);
clickBtn && (clickBtn.onclick = function(){
if (_this.options.beforeCheck()) {
_this.$element.find(".mask").css("display","block");
}
})
}
//按下
this.htmlDoms.move_block.on('touchstart', function(e) {
_this.start(e);
});
this.htmlDoms.move_block.on('mousedown', function(e) {
_this.start(e);
});
//拖动
window.addEventListener("touchmove", function(e) {
_this.move(e);
});
window.addEventListener("mousemove", function(e) {
_this.move(e);
});
//鼠标松开
window.addEventListener("touchend", function() {
_this.end();
});
window.addEventListener("mouseup", function() {
_this.end();
});
//刷新
_this.$element.find('.verify-refresh').on('click', function() {
_this.refresh();
});
},
//初始化加载
loadDom : function() {
this.status = false; //鼠标状态
this.isEnd = false; //是够验证完成
this.setSize = this.resetSize(this); //重新设置宽度高度
this.plusWidth = 0;
this.plusHeight = 0;
this.x = 0;
this.y = 0;
var panelHtml = '';
var wrapHtml = '';
this.lengthPercent = (parseInt(this.setSize.img_width)-parseInt(this.setSize.block_width)- parseInt(this.setSize.circle_radius) - parseInt(this.setSize.circle_radius) * 0.8)/(parseInt(this.setSize.img_width)-parseInt(this.setSize.bar_height));
wrapStartHtml = '<div class="mask">'+
'<div class="verifybox" style="width:'+(parseInt(this.setSize.img_width)+30)+'px">'+
'<div class="verifybox-top">'+
'请完成安全验证'+
'<span class="verifybox-close">'+
'<i class="iconfont icon-close"></i>'+
'</span>'+
'</div>'+
'<div class="verifybox-bottom" style="padding:10px 15px 15px 15px">'+
'<div style="position: relative;">';
if (this.options.mode == 'pop') {
panelHtml = wrapStartHtml
}
panelHtml += '<div class="verify-img-out">'+
'<div class="verify-img-panel">'+
'<div class="verify-refresh" style="z-index:3">'+
'<img src="data:image/png;base64,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">'+
'</div>'+
'<span class="verify-tips" class="suc-bg"></span>'+
'<img src="" class="backImg" style="width:100%;height:100%;display:block">'+
'</div>'+
'</div>';
this.plusWidth = parseInt(this.setSize.block_width) + parseInt(this.setSize.circle_radius) * 2 - parseInt(this.setSize.circle_radius) * 0.2;
this.plusHeight = parseInt(this.setSize.block_height) + parseInt(this.setSize.circle_radius) * 2 - parseInt(this.setSize.circle_radius) * 0.2;
panelHtml +='<div class="verify-bar-area" style="width:'+this.setSize.img_width+',height:'+this.setSize.bar_height+',line-height:'+this.setSize.bar_height+'">'+
'<span class="verify-msg">'+this.options.explain+'</span>'+
'<div class="verify-left-bar">'+
'<span class="verify-msg"></span>'+
'<div class="verify-move-block">'+
'<i class="verify-icon iconfont icon-right"></i>'+
'<div class="verify-sub-block">'+
'<img src="" class="bock-backImg" alt="" style="width:100%;height:100%;display:block">'+
'</div>'+
'</div>'+
'</div>'+
'</div>';
wrapEndHtml = '</div></div></div></div>';
if (this.options.mode == 'pop') {
panelHtml += wrapEndHtml
}
this.$element.append(panelHtml);
this.htmlDoms = {
tips: this.$element.find('.verify-tips'),
sub_block : this.$element.find('.verify-sub-block'),
out_panel : this.$element.find('.verify-img-out'),
img_panel : this.$element.find('.verify-img-panel'),
img_canvas : this.$element.find('.verify-img-canvas'),
bar_area : this.$element.find('.verify-bar-area'),
move_block : this.$element.find('.verify-move-block'),
left_bar : this.$element.find('.verify-left-bar'),
msg : this.$element.find('.verify-msg'),
icon : this.$element.find('.verify-icon'),
refresh :this.$element.find('.verify-refresh')
};
this.$element.css('position', 'relative');
this.htmlDoms.sub_block.css({'height':this.setSize.img_height,'width':Math.floor(parseInt(this.setSize.img_width)*47/310)+ 'px',
'top':-(parseInt(this.setSize.img_height) + this.options.vSpace) + 'px'})
this.htmlDoms.out_panel.css('height', parseInt(this.setSize.img_height) + this.options.vSpace + 'px');
this.htmlDoms.img_panel.css({'width': this.setSize.img_width, 'height': this.setSize.img_height});
this.htmlDoms.bar_area.css({'width': this.setSize.img_width, 'height': this.setSize.bar_height, 'line-height':this.setSize.bar_height});
this.htmlDoms.move_block.css({'width': this.setSize.bar_height, 'height': this.setSize.bar_height});
this.htmlDoms.left_bar.css({'width': this.setSize.bar_height, 'height': this.setSize.bar_height});
},
//鼠标按下
start: function(e) {
if(!e.originalEvent.targetTouches) { //兼容移动端
var x = e.clientX;
}else { //兼容PC端
var x = e.originalEvent.targetTouches[0].pageX;
}
// if(!e.touches) { //兼容移动端
// var x = e.clientX;
// }else { //兼容PC端
// var x = e.touches[0].pageX;
// }
this.startLeft = Math.floor(x - this.htmlDoms.bar_area[0].getBoundingClientRect().left);
this.startMoveTime = new Date().getTime();
if(this.isEnd == false) {
this.htmlDoms.msg.text('');
this.htmlDoms.move_block.css('background-color', '#337ab7');
this.htmlDoms.left_bar.css('border-color', '#337AB7');
this.htmlDoms.icon.css('color', '#fff');
e.stopPropagation();
this.status = true;
}
},
//鼠标移动
move: function(e) {
if(this.status && this.isEnd == false) {
if(!e.touches) { //兼容移动端
var x = e.clientX;
}else { //兼容PC端
var x = e.touches[0].pageX;
}
var bar_area_left = this.htmlDoms.bar_area[0].getBoundingClientRect().left;
var move_block_left = x - bar_area_left; //小方块相对于父元素的left值
if(move_block_left >= (this.htmlDoms.bar_area[0].offsetWidth - parseInt(this.setSize.bar_height) + parseInt(parseInt(this.setSize.block_width)/2) - 2) ) {
move_block_left = (this.htmlDoms.bar_area[0].offsetWidth - parseInt(this.setSize.bar_height) + parseInt(parseInt(this.setSize.block_width)/2)- 2);
}
if(move_block_left <= parseInt(parseInt(this.setSize.block_width)/2)) {
move_block_left = parseInt(parseInt(this.setSize.block_width)/2);
}
//拖动后小方块的left值
this.htmlDoms.move_block.css('left', move_block_left-this.startLeft + "px");
this.htmlDoms.left_bar.css('width', move_block_left-this.startLeft + "px");
this.htmlDoms.sub_block.css('left', "0px");
this.moveLeftDistance = move_block_left - this.startLeft
}
},
//鼠标松开
end: function() {
this.endMovetime = new Date().getTime();
var _this = this;
//判断是否重合
if(this.status && this.isEnd == false) {
var vOffset = parseInt(this.options.vOffset);
this.moveLeftDistance = this.moveLeftDistance * 310/ parseInt(this.setSize.img_width)
//图片滑动
var data = {
captchaType:this.options.captchaType,
"pointJson": this.secretKey ? aesEncrypt(JSON.stringify({x:this.moveLeftDistance,y:5.0}),this.secretKey):JSON.stringify({x:this.moveLeftDistance,y:5.0}),
"token":this.backToken,
clientUid: localStorage.getItem('slider'),
ts: Date.now()
}
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken+'---'+JSON.stringify({x:this.moveLeftDistance,y:5.0}),this.secretKey):this.backToken+'---'+JSON.stringify({x:this.moveLeftDistance,y:5.0})
checkPictrue(data,this.options.baseUrl,function(res){
// 请求反正成功的判断
if (res.repCode=="0000") {
_this.htmlDoms.move_block.css('background-color', '#5cb85c');
_this.htmlDoms.left_bar.css({'border-color': '#5cb85c', 'background-color': '#fff'});
_this.htmlDoms.icon.css('color', '#fff');
_this.htmlDoms.icon.removeClass('icon-right');
_this.htmlDoms.icon.addClass('icon-check');
//提示框
_this.htmlDoms.tips.addClass('suc-bg').removeClass('err-bg')
_this.htmlDoms.tips.css({"display":"block",animation:"move 1s cubic-bezier(0, 0, 0.39, 1.01)"});
_this.htmlDoms.tips.text(((_this.endMovetime-_this.startMoveTime)/1000).toFixed(2) + 's验证成功');
_this.isEnd = true;
setTimeout(function(){
_this.$element.find(".mask").css("display","none");
_this.htmlDoms.tips.css({"display":"none",animation:"none"});
_this.refresh();
}, 1000)
_this.options.success({'__captchaVerification':captchaVerification});
}else{
_this.htmlDoms.move_block.css('background-color', '#d9534f');
_this.htmlDoms.left_bar.css('border-color', '#d9534f');
_this.htmlDoms.icon.css('color', '#fff');
_this.htmlDoms.icon.removeClass('icon-right');
_this.htmlDoms.icon.addClass('icon-close');
_this.htmlDoms.tips.addClass('err-bg').removeClass('suc-bg')
_this.htmlDoms.tips.css({"display":"block",animation:"move 1.3s cubic-bezier(0, 0, 0.39, 1.01)"});
_this.htmlDoms.tips.text(res.repMsg)
setTimeout(function () {
_this.refresh();
}, 800);
setTimeout(function () {
_this.htmlDoms.tips.css({"display":"none",animation:"none"});
}, 1300)
_this.options.error(this);
}
})
this.status = false;
}
},
resetSize : function(obj) {
var img_width,img_height,bar_width,bar_height,block_width,block_height,circle_radius; //图片的宽度、高度,移动条的宽度、高度
var parentWidth = obj.$element.parent().width() || $(window).width();
var parentHeight = obj.$element.parent().height() || $(window).height();
if(obj.options.imgSize.width.indexOf('%')!= -1){
img_width = parseInt(obj.options.imgSize.width)/100 * parentWidth + 'px';
  }else {
img_width = obj.options.imgSize.width;
}
if(obj.options.imgSize.height.indexOf('%')!= -1){
img_height = parseInt(obj.options.imgSize.height)/100 * parentHeight + 'px';
  }else {
img_height = obj.options.imgSize.height;
}
if(obj.options.barSize.width.indexOf('%')!= -1){
bar_width = parseInt(obj.options.barSize.width)/100 * parentWidth + 'px';
  }else {
bar_width = obj.options.barSize.width;
}
if(obj.options.barSize.height.indexOf('%')!= -1){
bar_height = parseInt(obj.options.barSize.height)/100 * parentHeight + 'px';
  }else {
bar_height = obj.options.barSize.height;
}
if(obj.options.blockSize) {
if(obj.options.blockSize.width.indexOf('%')!= -1){
block_width = parseInt(obj.options.blockSize.width)/100 * parentWidth + 'px';
  }else {
block_width = obj.options.blockSize.width;
}
if(obj.options.blockSize.height.indexOf('%')!= -1){
block_height = parseInt(obj.options.blockSize.height)/100 * parentHeight + 'px';
  }else {
block_height = obj.options.blockSize.height;
}
}
if(obj.options.circleRadius) {
if(obj.options.circleRadius.indexOf('%')!= -1){
circle_radius = parseInt(obj.options.circleRadius)/100 * parentHeight + 'px';
  }else {
circle_radius = obj.options.circleRadius;
}
}
return {img_width : img_width, img_height : img_height, bar_width : bar_width, bar_height : bar_height, block_width : block_width, block_height : block_height, circle_radius : circle_radius};
},
//刷新
refresh: function() {
var _this = this;
this.htmlDoms.refresh.show();
this.$element.find('.verify-msg:eq(1)').text('');
this.$element.find('.verify-msg:eq(1)').css('color', '#000');
this.htmlDoms.move_block.animate({'left':'0px'}, 'fast');
this.htmlDoms.left_bar.animate({'width': parseInt(this.setSize.bar_height)}, 'fast');
this.htmlDoms.left_bar.css({'border-color': '#ddd'});
this.htmlDoms.move_block.css('background-color', '#fff');
this.htmlDoms.icon.css('color', '#000');
this.htmlDoms.icon.removeClass('icon-close');
this.htmlDoms.icon.addClass('icon-right');
this.$element.find('.verify-msg:eq(0)').text(this.options.explain);
this.isEnd = false;
getPictrue({captchaType:"blockPuzzle", clientUid: localStorage.getItem('slider'), ts: Date.now()},this.options.baseUrl,function (res) {
if (res.repCode=="0000") {
_this.$element.find(".backImg")[0].src = 'data:image/png;base64,'+res.repData.originalImageBase64
_this.$element.find(".bock-backImg")[0].src = 'data:image/png;base64,'+res.repData.jigsawImageBase64
_this.secretKey = res.repData.secretKey
_this.backToken = res.repData.token
} else {
_this.$element.find(".backImg")[0].src = 'images/default.jpg'
_this.$element.find(".bock-backImg")[0].src = ''
_this.htmlDoms.tips.addClass('err-bg').removeClass('suc-bg')
_this.htmlDoms.tips.animate({"bottom":"0px"});
_this.htmlDoms.tips.text(res.repMsg)
setTimeout(function () {
_this.htmlDoms.tips.animate({"bottom":"-35px"});
}, 1000);
}
});
this.htmlDoms.sub_block.css('left', "0px");
},
};
//定义Points的构造函数
var Points = function(ele, opt) {
this.$element = ele,
this.backToken = null,
this.secretKey = '',
this.defaults = {
baseUrl:"https://captcha.anji-plus.com/captcha-api",
captchaType:"clickWord",
containerId:'',
mode : 'fixed', //弹出式pop固定fixed
checkNum : 3, //校对的文字数量
vSpace : 5, //间隔
explain : '向右拖动滑块填充拼图',
imgSize : {
width: '310px',
height: '155px',
},
barSize : {
width : '310px',
height : '50px',
},
beforeCheck: function(){ return true},
ready : function(){},
success : function(){},
error : function(){}
},
this.options = $.extend({}, this.defaults, opt)
};
//定义Points的方法
Points.prototype = {
init : function() {
var _this = this;
//加载页面
_this.loadDom();
_this.refresh();
_this.options.ready();
this.$element[0].onselectstart = document.body.ondrag = function(){
return false;
};
if(this.options.mode == 'pop') {
_this.$element.find('.verifybox-close').on('click', function() {
_this.$element.find(".mask").css("display","none");
});
var clickBtn = document.getElementById(this.options.containerId);
clickBtn && (clickBtn.onclick = function(){
if (_this.options.beforeCheck()) {
_this.$element.find(".mask").css("display","block");
}
})
}
// 注册点击验证事件
_this.$element.find('.back-img').on('click', function(e) {
_this.checkPosArr.push(_this.getMousePos(this, e));
if(_this.num == _this.options.checkNum) {
_this.num = _this.createPoint(_this.getMousePos(this, e));
//按比例转换坐标值
_this.checkPosArr = _this.pointTransfrom(_this.checkPosArr,_this.setSize);
setTimeout(function(){
var data = {
captchaType:_this.options.captchaType,
"pointJson":_this.secretKey ? aesEncrypt(JSON.stringify(_this.checkPosArr),_this.secretKey):JSON.stringify(_this.checkPosArr),
"token":_this.backToken,
clientUid: localStorage.getItem('point'),
ts: Date.now()
}
var captchaVerification = _this.secretKey ? aesEncrypt(_this.backToken+'---'+JSON.stringify(_this.checkPosArr),_this.secretKey):_this.backToken+'---'+JSON.stringify(_this.checkPosArr)
checkPictrue(data, _this.options.baseUrl,function(res){
if (res.repCode=="0000") {
_this.$element.find('.verify-bar-area').css({'color': '#4cae4c', 'border-color': '#5cb85c'});
_this.$element.find('.verify-msg').text('验证成功');
// _this.$element.find('.verify-refresh').hide();
_this.$element.find('.verify-img-panel').unbind('click');
setTimeout(function(){
_this.$element.find(".mask").css("display","none");
_this.refresh();
},1000)
_this.options.success({'captchaVerification':captchaVerification});
}else{
_this.options.error(_this);
_this.$element.find('.verify-bar-area').css({'color': '#d9534f', 'border-color': '#d9534f'});
_this.$element.find('.verify-msg').text('验证失败');
setTimeout(function () {
_this.$element.find('.verify-bar-area').css({'color': '#000','border-color': '#ddd'});
_this.refresh();
}, 400);
}
})
}, 400);
}
if(_this.num < _this.options.checkNum) {
_this.num = _this.createPoint(_this.getMousePos(this, e));
}
});
//刷新
_this.$element.find('.verify-refresh').on('click', function() {
_this.refresh();
});
},
//加载页面
loadDom : function() {
this.fontPos = []; //选中的坐标信息
this.checkPosArr = []; //用户点击的坐标
this.num = 1; //点击的记数
var panelHtml = '';
var wrapStartHtml = '';
this.setSize = Slide.prototype.resetSize(this); //重新设置宽度高度
wrapStartHtml = '<div class="mask">'+
'<div class="verifybox" style="width:'+(parseInt(this.setSize.img_width)+30)+'px">'+
'<div class="verifybox-top">'+
'请完成安全验证'+
'<span class="verifybox-close">'+
'<i class="iconfont icon-close"></i>'+
'</span>'+
'</div>'+
'<div class="verifybox-bottom" style="padding:15px">'+
'<div style="position: relative;">';
if (this.options.mode == 'pop') {
panelHtml = wrapStartHtml
}
panelHtml += '<div class="verify-img-out">'+
'<div class="verify-img-panel">'+
'<div class="verify-refresh" style="z-index:3">'+
'<i class="iconfont icon-refresh"></i>'+
'</div>'+
'<img src="" class="back-img" width="'+this.setSize.img_width+'" height="'+this.setSize.img_height+'">'+
'</div>'+
'</div>'+
'<div class="verify-bar-area" style="width:'+this.setSize.img_width+',height:'+this.setSize.bar_height+',line-height:'+this.setSize.bar_height+'">'+
'<span class="verify-msg"></span>'+
'</div>';
wrapEndHtml = '</div></div></div></div>';
if (this.options.mode == 'pop') {
panelHtml += wrapEndHtml
}
this.$element.append(panelHtml);
this.htmlDoms = {
back_img : this.$element.find('.back-img'),
out_panel : this.$element.find('.verify-img-out'),
img_panel : this.$element.find('.verify-img-panel'),
bar_area : this.$element.find('.verify-bar-area'),
msg : this.$element.find('.verify-msg'),
};
this.$element.css('position', 'relative');
this.htmlDoms.out_panel.css('height', parseInt(this.setSize.img_height) + this.options.vSpace + 'px');
this.htmlDoms.img_panel.css({'width': this.setSize.img_width, 'height': this.setSize.img_height, 'background-size' : this.setSize.img_width + ' '+ this.setSize.img_height, 'margin-bottom': this.options.vSpace + 'px'});
this.htmlDoms.bar_area.css({'width': this.setSize.img_width, 'height': this.setSize.bar_height, 'line-height':this.setSize.bar_height});
},
//获取坐标
getMousePos :function(obj, event) {
var e = event || window.event;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var x = e.clientX - ($(obj).offset().left - $(window).scrollLeft());
var y = e.clientY - ($(obj).offset().top - $(window).scrollTop());
return {'x': x, 'y': y};
},
//创建坐标点
createPoint : function (pos) {
this.htmlDoms.img_panel.append('<div class="point-area" style="background-color:#1abd6c;color:#fff;z-index:9999;width:20px;height:20px;text-align:center;line-height:20px;border-radius: 50%;position:absolute;'
+'top:'+parseInt(pos.y-10)+'px;left:'+parseInt(pos.x-10)+'px;">'+this.num+'</div>');
return ++this.num;
},
//刷新
refresh: function() {
var _this = this;
this.$element.find('.point-area').remove();
this.fontPos = [];
this.checkPosArr = [];
this.num = 1;
getPictrue({captchaType:"clickWord", clientUid: localStorage.getItem('point'), ts: Date.now()},_this.options.baseUrl,function(res){
if (res.repCode=="0000") {
_this.htmlDoms.back_img[0].src ='data:image/png;base64,'+ res.repData.originalImageBase64;
_this.backToken = res.repData.token;
_this.secretKey = res.repData.secretKey;
var text = '请依次点击【' + res.repData.wordList.join(",") + '】';
_this.$element.find('.verify-msg').text(text);
} else {
_this.htmlDoms.back_img[0].src = 'images/default.jpg';
_this.$element.find('.verify-msg').text(res.repMsg);
}
})
},
pointTransfrom:function(pointArr,imgSize){
var newPointArr = pointArr.map(function(p){
var x = Math.round(310 * p.x/parseInt(imgSize.img_width))
var y =Math.round(155 * p.y/parseInt(imgSize.img_height))
return {'x':x,'y':y}
})
return newPointArr
}
};
//在插件中使用slideVerify对象
$.fn.slideVerify = function(options, callbacks) {
var slide = new Slide(this, options);
if (slide.options.mode=="pop" && slide.options.beforeCheck()) {
slide.init();
}else if (slide.options.mode=="fixed") {
slide.init();
}
};
//在插件中使用clickVerify对象
$.fn.pointsVerify = function(options, callbacks) {
var points = new Points(this, options);
if (points.options.mode=="pop" && points.options.beforeCheck()) {
points.init();
}else if (points.options.mode=="fixed") {
points.init();
}
};
})(jQuery, window, document);

File diff suppressed because one or more lines are too long

@ -2,39 +2,29 @@
$(function() {
validateKickout();
validateRule();
$('.imgcode').click(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url);
});
refreshCode();
});
$.validator.setDefaults({
submitHandler: function() {
login();
showVerfyImage();
}
});
function login() {
function showVerfyImage() {
$("#verfyImg").find(".mask").css("display", "block");
}
function postLogin(data){
$.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var validateCode = $("input[name='validateCode']").val();
var rememberMe = $("input[name='rememberme']").is(':checked');
$.ajax({
type: "post",
url: ctx + "login",
data: {
"username": username,
"password": password,
"validateCode": validateCode,
"rememberMe": rememberMe
},
data: data,
success: function(r) {
if (r.code == web_status.SUCCESS) {
location.href = ctx + 'index';
} else {
$('.imgcode').click();
$(".code").val("");
$.modal.msg(r.msg);
}
$.modal.closeLoading();
@ -42,6 +32,28 @@ function login() {
});
}
/* 刷新验证码 */
function refreshCode() {
/** 初始化验证码 弹出式 */
$('#verfyImg').slideVerify({
baseUrl: ctx,
mode: 'pop',
success : function(params) {
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var rememberMe = $("input[name='rememberme']").is(':checked');
var data = {
"username": username,
"password": password,
"rememberMe": rememberMe
};
data = $.extend(data, params);
postLogin(data);
},
error : function() {}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({

@ -1,33 +1,28 @@
$(function() {
validateRule();
$('.imgcode').click(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url);
});
refreshCode();
});
$.validator.setDefaults({
submitHandler: function() {
register();
showVerfyImage();
}
});
function register() {
$.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var validateCode = $("input[name='validateCode']").val();
function showVerfyImage() {
$("#verfyImg").find(".mask").css("display", "block");
}
function postRegister(data){
$.modal.loading($("#btnSubmit").data("loading"));
$.ajax({
type: "post",
url: ctx + "register",
data: {
"loginName": username,
"password": password,
"validateCode": validateCode
},
data: data,
success: function(r) {
if (r.code == web_status.SUCCESS) {
var username = $.common.trim($("input[name='username']").val());
layer.alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", {
icon: 1,
title: "系统提示"
@ -39,14 +34,32 @@ function register() {
});
} else {
$.modal.closeLoading();
$('.imgcode').click();
$(".code").val("");
$.modal.msg(r.msg);
}
}
});
}
/* 刷新验证码 */
function refreshCode() {
/** 初始化验证码 弹出式 */
$('#verfyImg').slideVerify({
baseUrl: ctx,
mode: 'pop',
success : function(params) {
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var data = {
"loginName": username,
"password": password
};
data = $.extend(data, params);
postRegister(data);
},
error : function() {}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#registerForm").validate({

@ -4,12 +4,13 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>甘肃省人民检察院兰铁分院系统</title>
<meta name="description" content="若依后台管理框架">
<meta name="description" content="甘肃省人民检察院兰铁分院系统">
<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.7}" rel="stylesheet"/>
<link href="../static/ajax/libs/captcha/css/verify.min.css" th:href="@{/ajax/libs/captcha/css/verify.min.css}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@ -35,58 +36,64 @@
width: 26%;
top: 6%;
}
.verifybox {
left: 70%;
top: 42%;
transform: translate(-52%, -50%);
}
</style>
<script>
if(window.top!==window.self){alert('未登录或登录超时。请重新登录');window.top.location=window.location};
</script>
</head>
<body class="signin">
<div class="signinpanel">
<div class="row" style="margin-right: -30px">
<div class="col-sm-7">
<div class="signin-info">
<div class="logopanel m-b">
</div>
<div class="m-b"></div>
<h2><strong>欢迎使用</strong></h2>
<h4> <strong>甘肃省人民检察院兰铁分院网站后台管理系统</strong></h4>
<ul class="m-b">
</ul>
<strong th:if="${isAllowRegister}">还没有账号? <a th:href="@{/register}">立即注册&raquo;</a></strong>
<div id="verfyImg">
</div>
<div class="signinpanel">
<div class="row" style="margin-right: -30px">
<div class="col-sm-7">
<div class="signin-info">
<div class="logopanel m-b">
</div>
</div>
<div class="col-sm-5">
<form id="signupForm" autocomplete="off">
<h4 class="no-margins" style="color:#000;">登录:</h4>
<input type="text" name="username" class="form-control uname" placeholder="用户名" value="admin" />
<input type="password" name="password" class="form-control pword" placeholder="密码" value="admin123" />
<div class="row m-t" th:if="${captchaEnabled==true}">
<div class="col-xs-6">
<input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" />
</div>
<div class="col-xs-6">
<a href="javascript:void(0);" title="点击更换验证码">
<img th:src="@{/captcha/captchaImage(type=${captchaType})}" class="imgcode" width="85%"/>
</a>
</div>
</div>
<div class="checkbox-custom" th:if="${isRemembered}" th:classappend="${captchaEnabled==false} ? 'm-t'">
<input type="checkbox" id="rememberme" name="rememberme"> <label style="color: #000;" for="rememberme">记住我</label>
</div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证登录,请稍候...">登录</button>
</form>
<div class="m-b"></div>
<h2><strong>欢迎使用</strong></h2>
<h4> <strong>甘肃省人民检察院兰铁分院网站后台管理系统</strong></h4>
<ul class="m-b">
</ul>
<strong th:if="${isAllowRegister}">还没有账号? <a th:href="@{/register}">立即注册&raquo;</a></strong>
</div>
</div>
<div class="signup-footer" style="position: absolute;bottom: 3% ;left: 5% ;">
<div class="pull-left">
Copyright ©甘肃省人民检察院兰铁分院<br>
</div>
<div class="col-sm-5">
<form id="signupForm" autocomplete="off">
<h4 class="no-margins" style="color:#000;">登录:</h4>
<p class="m-t-md"></p>
<input type="text" name="username" class="form-control uname" placeholder="用户名" value="" />
<input type="password" name="password" class="form-control pword" placeholder="密码" value="" />
<div class="checkbox-custom m-t" th:if="${isRemembered}">
<input type="checkbox" id="rememberme" name="rememberme"> <label style="color: #000;" for="rememberme">记住我</label>
</div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证登录,请稍后...">登录</button>
</form>
</div>
</div>
<div class="signup-footer" style="position: absolute;bottom: 3% ;left: 5% ;">
<div class="pull-left">
Copyright ©甘肃省人民检察院兰铁分院<br>
</div>
</div>
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; </script>
</div>
<script th:inline="javascript"> var ctx = [[@{/}]];</script>
<!--[if lte IE 8]><script>window.location.href=ctx+'html/ie.html';</script><![endif]-->
<!-- 全局js -->
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
<!-- 验证码 -->
<script src="../static/ajax/libs/captcha/crypto-js.min.js" th:src="@{/ajax/libs/captcha/crypto-js.min.js}"></script>
<script src="../static/ajax/libs/captcha/ase.min.js" th:src="@{/ajax/libs/captcha/ase.min.js}"></script>
<script src="../static/ajax/libs/captcha/verify.min.js" th:src="@{/ajax/libs/captcha/verify.min.js}"></script>
<!-- 验证插件 -->
<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>

@ -4,17 +4,18 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>甘肃省人民检察院兰铁分院系统</title>
<meta name="description" content="若依后台管理框架">
<meta name="description" content="甘肃省人民检察院兰铁分院系统">
<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.7}" rel="stylesheet"/>
<link href="../static/ajax/libs/captcha/css/verify.min.css" th:href="@{/ajax/libs/captcha/css/verify.min.css}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="shortcut icon" th:href="@{/home/base/favicon.ico}" />
<link th:href="@{/home/base/favicon.ico}" rel="shortcut icon"/>
<style type="text/css">label.error { position:inherit; }
.signinpanel {
width: 100%;
@ -35,62 +36,57 @@
width: 26%;
top: 6%;
}
.verifybox {
left: 70%;
top: 46%;
transform: translate(-52%, -50%);
}
</style>
</head>
<body class="signin">
<div class="signinpanel">
<div class="row">
<div class="col-sm-7">
<div class="signin-info">
<div class="logopanel m-b">
<!--<h1><img alt="[ 若依 ]" src="../static/ruoyi.png" th:src="@{/ruoyi.png}"></h1>-->
</div>
<div class="m-b"></div>
<h4>欢迎使用 <strong>甘肃省人民检察院兰铁分院门户网站后台管理系统</strong></h4>
<!--<ul class="m-b">
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> SpringBoot</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Mybatis</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Shiro</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Thymeleaf</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Bootstrap</li>
</ul>-->
<strong>已经注册过? <a th:href="@{/login}">直接登录&raquo;</a></strong>
<div id="verfyImg">
</div>
<div class="signinpanel">
<div class="row">
<div class="col-sm-7">
<div class="signin-info">
<div class="logopanel m-b">
<!--<h1><img alt="[ 若依 ]" src="../static/ruoyi.png" th:src="@{/ruoyi.png}"></h1>-->
</div>
</div>
<div class="col-sm-5">
<form id="registerForm" autocomplete="off">
<h4 class="no-margins" style="color:#000;">注册:</h4>
<input type="text" name="username" class="form-control uname" placeholder="用户名" maxlength="20" />
<input type="password" name="password" class="form-control pword" placeholder="密码" maxlength="20" />
<input type="password" name="confirmPassword" class="form-control pword" placeholder="确认密码" maxlength="20" />
<div class="row m-t" th:if="${captchaEnabled==true}">
<div class="col-xs-6">
<input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" >
</div>
<div class="col-xs-6">
<a href="javascript:void(0);" title="点击更换验证码">
<img th:src="@{/captcha/captchaImage(type=${captchaType})}" class="imgcode" width="85%"/>
</a>
</div>
</div>
<div class="checkbox-custom" th:classappend="${captchaEnabled==false} ? 'm-t'">
<input type="checkbox" id="acceptTerm" name="acceptTerm"> <label for="acceptTerm">我已阅读并同意</label>
<a href="https://gitee.com/y_project/RuoYi/blob/master/README.md" target="_blank">使用条款</a>
</div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证注册,请稍候...">注册</button>
</form>
<div class="m-b"></div>
<h4>欢迎使用 <strong>甘肃省人民检察院兰铁分院门户网站后台管理系统</strong></h4>
<strong>已经注册过? <a th:href="@{/login}">直接登录&raquo;</a></strong>
</div>
</div>
<div class="signup-footer" style="position: absolute;bottom: 3% ;left: 5% ;">
<div class="pull-left">
Copyright ©甘肃省人民检察院兰铁分院<br>
</div>
<div class="col-sm-5">
<form id="registerForm" autocomplete="off">
<h4 class="no-margins">注册:</h4>
<p class="m-t-md">你若不离不弃,我必生死相依</p>
<input type="text" name="username" class="form-control uname" placeholder="用户名" maxlength="20" />
<input type="password" name="password" class="form-control pword" placeholder="密码" maxlength="20" />
<input type="password" name="confirmPassword" class="form-control pword" placeholder="确认密码" maxlength="20" />
<div class="checkbox-custom m-t">
<input type="checkbox" id="acceptTerm" name="acceptTerm"> <label style="color: #000;" for="acceptTerm">我已阅读并同意</label>
</div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证注册,请稍后...">注册</button>
</form>
</div>
</div>
<div class="signup-footer" style="position: absolute;bottom: 3% ;left: 5% ;">
<div class="pull-left">
Copyright ©甘肃省人民检察院兰铁分院<br>
</div>
</div>
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; </script>
</div>
<script th:inline="javascript"> var ctx = [[@{/}]];</script>
<!-- 全局js -->
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
<!-- 验证码 -->
<script src="../static/ajax/libs/captcha/crypto-js.min.js" th:src="@{/ajax/libs/captcha/crypto-js.min.js}"></script>
<script src="../static/ajax/libs/captcha/ase.min.js" th:src="@{/ajax/libs/captcha/ase.min.js}"></script>
<script src="../static/ajax/libs/captcha/verify.min.js" th:src="@{/ajax/libs/captcha/verify.min.js}"></script>
<!-- 验证插件 -->
<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>

@ -77,6 +77,13 @@
<artifactId>ruoyi-system</artifactId>
</dependency>
<!-- 滑块验证码 -->
<dependency>
<groupId>com.github.anji-plus</groupId>
<artifactId>captcha-spring-boot-starter</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>
</project>

@ -17,10 +17,13 @@ import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import com.anji.captcha.service.CaptchaService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.CipherUtils;
@ -129,6 +132,10 @@ public class ShiroConfig
*/
@Value("${shiro.rememberMe.enabled: false}")
private boolean rememberMe;
@Autowired
@Lazy
private CaptchaService captchaService;
/**
* 使Ehcache
@ -288,10 +295,13 @@ public class ShiroConfig
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/ruoyi/**", "anon");
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
filterChainDefinitionMap.put("/captcha/**", "anon");
// 退出 logout地址shiro去清除session
filterChainDefinitionMap.put("/logout", "logout");
// 不需要拦截的访问
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
// 注册相关
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
// 不需要拦截的访问门户
filterChainDefinitionMap.put("/home/**", "anon");
filterChainDefinitionMap.put("/home", "anon,captchaValidate");
@ -304,9 +314,6 @@ public class ShiroConfig
filterChainDefinitionMap.put("/public_view.html", "anon");
filterChainDefinitionMap.put("/profile/**", "anon");
filterChainDefinitionMap.put("/search", "anon");
// 注册相关
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
// 系统权限列表
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
@ -354,7 +361,7 @@ public class ShiroConfig
{
CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
captchaValidateFilter.setCaptchaEnabled(captchaEnabled);
captchaValidateFilter.setCaptchaType(captchaType);
captchaValidateFilter.setCaptchaService(captchaService);
return captchaValidateFilter;
}

@ -4,9 +4,9 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.web.filter.AccessControlFilter;
import com.google.code.kaptcha.Constants;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
/**
@ -21,26 +21,17 @@ public class CaptchaValidateFilter extends AccessControlFilter
*/
private boolean captchaEnabled = true;
/**
*
*/
private String captchaType = "math";
private CaptchaService captchaService;
public void setCaptchaEnabled(boolean captchaEnabled)
{
this.captchaEnabled = captchaEnabled;
}
public void setCaptchaType(String captchaType)
{
this.captchaType = captchaType;
}
@Override
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
{
request.setAttribute(ShiroConstants.CURRENT_ENABLED, captchaEnabled);
request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType);
return super.onPreHandle(request, response, mappedValue);
}
@ -54,16 +45,14 @@ public class CaptchaValidateFilter extends AccessControlFilter
{
return true;
}
return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE));
return validateResponse(httpServletRequest, httpServletRequest.getParameter("__captchaVerification"));
}
public boolean validateResponse(HttpServletRequest request, String validateCode)
public boolean validateResponse(HttpServletRequest request, String captchaVerification)
{
Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
String code = String.valueOf(obj != null ? obj : "");
// 验证码清除,防止多次使用。
request.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
CaptchaVO captchaVO = new CaptchaVO();
captchaVO.setCaptchaVerification(captchaVerification);
if (StringUtils.isEmpty(captchaVerification) || !captchaService.verification(captchaVO).isSuccess())
{
return false;
}
@ -76,4 +65,9 @@ public class CaptchaValidateFilter extends AccessControlFilter
request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR);
return true;
}
}
public void setCaptchaService(CaptchaService captchaService)
{
this.captchaService = captchaService;
}
}
Loading…
Cancel
Save