Toggle navigation
Toggle navigation
This project
Loading...
Sign in
fe
/
yohobuywap-node
·
Commits
Go to a project
GitLab
Go to group
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
0
Merge Requests
0
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Email Patches
Plain Diff
Browse Files
Authored by
yyq
7 years ago
Commit
6f3a12e9d22d95c7ef28c41ab4d21d8f45931359
1 parent
8ed52d06
api risk
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
253 additions
and
96 deletions
apps/3party/controllers/check.js
apps/3party/models/check.js
apps/3party/views/action/check.hbs
apps/passport/controllers/captcha.js
apps/passport/models/imgcheck.js
apps/passport/router.js
doraemon/middleware/error-handler.js
doraemon/middleware/limiter/rules/path-white-list.js
public/js/3party/check.page.js
public/js/plugin/img-check.js
public/scss/3party/check.page.css
apps/3party/controllers/check.js
View file @
6f3a12e
'use strict'
;
const
_
=
require
(
'lodash'
);
const
headerModel
=
require
(
'../../../doraemon/models/header'
);
const
checkModel
=
require
(
'..//models/check'
);
const
decodeURIComponent
=
require
(
'../../../utils/string-process'
).
decodeURIComponent
;
const
logger
=
global
.
yoho
.
logger
;
const
Geetest
=
require
(
'geetest'
);
...
...
@@ -14,7 +16,12 @@ const captcha = new Geetest({
exports
.
index
=
(
req
,
res
)
=>
{
req
.
yoho
.
captchaShow
=
false
;
res
.
locals
.
useGeetest
=
true
;
if
(
req
.
session
.
apiRiskValidate
)
{
res
.
locals
.
useRiskImg
=
true
;
}
else
{
res
.
locals
.
useGeetest
=
true
;
}
if
(
_
.
has
(
res
,
'locals.loadJsBefore'
))
{
res
.
locals
.
loadJsBefore
.
push
({
...
...
@@ -27,89 +34,129 @@ exports.index = (req, res) => {
}
];
}
res
.
render
(
'check'
,
{
pageHeader
:
headerModel
.
setNav
({
navTitle
:
'友情提醒'
}),
width750
:
true
,
localCss
:
true
});
};
exports
.
submit
=
(
req
,
res
)
=>
{
co
(
function
*
()
{
let
challenge
=
req
.
body
.
geetest_challenge
,
validate
=
req
.
body
.
geetest_validate
,
seccode
=
req
.
body
.
geetest_seccode
;
let
errRes
=
{
code
:
400
,
message
:
'验证码错误'
,
captchaShow
:
true
,
changeCaptcha
:
true
};
if
(
!
challenge
||
!
validate
||
!
seccode
)
{
return
res
.
json
(
errRes
);
const
submitValidate
=
{
errRes
:
{
code
:
400
,
message
:
'验证码错误'
,
captchaShow
:
true
,
changeCaptcha
:
true
},
clearLimitIp
(
req
)
{
let
remoteIp
=
req
.
yoho
.
clientIp
;
if
(
remoteIp
.
indexOf
(
','
)
>
0
)
{
let
arr
=
remoteIp
.
split
(
','
);
remoteIp
=
arr
[
0
];
}
let
geetestRes
=
yield
captcha
.
validate
({
challenge
,
validate
,
seccode
});
// pc:limiter:IP 和PC端共用
let
operations
=
[
cache
.
delAsync
(
`
pc
:
limiter
:
$
{
remoteIp
}
`
)];
if
(
geetestRes
)
{
logger
.
info
(
'geetest success'
);
// 验证码之后一小时之内不再限制qps
if
(
req
.
session
.
apiLimitValidate
||
req
.
session
.
apiRiskValidate
)
{
operations
.
push
(
cache
.
setAsync
(
`
$
{
config
.
app
}:
limiter
:
api
:
ishuman
:
$
{
remoteIp
}
`
,
1
,
config
.
LIMITER_IP_TIME
));
}
else
{
operations
.
push
(
cache
.
setAsync
(
`
$
{
config
.
app
}:
limiter
:
ishuman
:
$
{
remoteIp
}
`
,
1
,
config
.
LIMITER_IP_TIME
));
}
delete
req
.
session
.
apiLimitValidate
;
delete
req
.
session
.
apiRiskValidate
;
if
(
req
.
body
.
pid
)
{
let
riskPid
=
decodeURIComponent
(
req
.
body
.
pid
)
+
':'
+
_
.
get
(
req
.
yoho
,
'clientIp'
,
''
);
operations
.
push
(
cache
.
delAsync
(
riskPid
));
}
_
.
forEach
(
config
.
REQUEST_LIMIT
,
(
val
,
key
)
=>
{
operations
.
push
(
cache
.
delAsync
(
`
$
{
config
.
app
}
:
limiter
:
$
{
key
}
:
max
:
$
{
remoteIp
}
`
));
});
let
remoteIp
=
req
.
yoho
.
clientIp
;
return
Promise
.
all
(
operations
);
},
geetest
(
req
,
res
)
{
const
self
=
this
;
if
(
remoteIp
.
indexOf
(
','
)
>
0
)
{
let
arr
=
remoteIp
.
split
(
','
);
co
(
function
*
()
{
let
challenge
=
req
.
body
.
geetest_challenge
,
validate
=
req
.
body
.
geetest_validate
,
seccode
=
req
.
body
.
geetest_seccode
;
remoteIp
=
arr
[
0
];
if
(
!
challenge
||
!
validate
||
!
seccode
)
{
return
res
.
json
(
self
.
errRes
);
}
// pc:limiter:IP 和PC端共用
let
operations
=
[
cache
.
delAsync
(
`
pc
:
limiter
:
$
{
remoteIp
}
`
)];
let
geetestRes
=
yield
captcha
.
validate
({
challenge
,
validate
,
seccode
});
if
(
geetestRes
)
{
logger
.
info
(
'geetest success'
);
// 验证码之后一小时之内不再限制qps
if
(
req
.
session
.
apiLimitValidate
)
{
operations
.
push
(
cache
.
setAsync
(
`
$
{
config
.
app
}:
limiter
:
api
:
ishuman
:
$
{
remoteIp
}
`
,
1
,
config
.
LIMITER_IP_TIME
));
yield
self
.
clearLimitIp
(
req
);
return
res
.
json
({
code
:
200
});
}
else
{
operations
.
push
(
cache
.
setAsync
(
`
$
{
config
.
app
}
:
limiter
:
ishuman
:
$
{
remoteIp
}
`
,
1
,
config
.
LIMITER_IP_TIME
));
logger
.
info
(
'geetest faild'
);
return
res
.
json
(
self
.
errRes
);
}
delete
req
.
session
.
apiLimitValidate
;
})();
},
imgCheckRisk
(
req
,
res
)
{
const
self
=
this
;
if
(
req
.
body
.
pid
)
{
let
riskPid
=
decodeURIComponent
(
req
.
body
.
pid
)
+
':'
+
_
.
get
(
req
.
yoho
,
'clientIp'
,
''
);
co
(
function
*
()
{
let
result
=
yield
req
.
ctx
(
checkModel
).
verifyImgCheckRisk
(
req
.
cookies
.
udid
,
req
.
body
.
captcha
);
operations
.
push
(
cache
.
delAsync
(
riskPid
));
}
if
(
result
.
code
===
200
)
{
yield
self
.
clearLimitIp
(
req
);
_
.
forEach
(
config
.
REQUEST_LIMIT
,
(
val
,
key
)
=>
{
operations
.
push
(
cache
.
delAsync
(
`
$
{
config
.
app
}
:
limiter
:
$
{
key
}
:
max
:
$
{
remoteIp
}
`
));
});
return
res
.
json
(
result
);
}
else
{
logger
.
info
(
'api risk img verify faild'
);
return
res
.
json
(
self
.
errRes
);
}
})();
}
};
yield
Promise
.
all
(
operations
);
exports
.
submit
=
(
req
,
res
)
=>
{
let
validateType
=
'geetest'
;
return
res
.
json
({
code
:
200
});
}
else
{
logger
.
info
(
'geetest faild'
);
return
res
.
json
(
errRes
);
}
if
(
req
.
session
.
apiRiskValidate
&&
req
.
body
.
apiRiskValidate
)
{
validateType
=
'imgCheckRisk'
;
}
})().
catch
(()
=>
{
try
{
return
submitValidate
[
validateType
](
req
,
res
);
}
catch
(
err
)
{
return
res
.
json
({
code
:
400
});
}
);
}
};
...
...
apps/3party/models/check.js
0 → 100644
View file @
6f3a12e
const
PAGE
=
'H5'
;
const
logger
=
global
.
yoho
.
logger
;
module
.
exports
=
class
extends
global
.
yoho
.
BaseModel
{
constructor
(
ctx
)
{
super
(
ctx
);
}
verifyImgCheckRisk
(
udid
,
degrees
)
{
return
this
.
get
({
data
:
{
method
:
'app.graphic.verify'
,
udid
:
udid
,
fromPage
:
PAGE
,
degrees
:
degrees
}
}).
then
(
result
=>
{
logger
.
info
(
`
app
.
graphic
.
verify
result
:
$
{
JSON
.
stringify
(
result
)}
`
);
return
result
;
});
}
};
...
...
apps/3party/views/action/check.hbs
View file @
6f3a12e
<div
class=
"check-page"
>
<div
class=
"title"
>
请确认之后,继续访问
</div>
<p
class=
"wran-tip"
>
<i
class=
"iconfont"
>

</i>
您的操作太频繁了~请完成以下操作后继续
</p>
{{!--图片验证--}}
<div
data-geetest=
"
{{
useGeetest
}}
"
id=
"js-img-check"
></div>
<div
{{#if
useGeetest
}}
data-geetest=
"true"
{{/if}}{{#if
useRiskImg
}}
data-riskimg=
"true"
{{/if}}
id=
"js-img-check"
></div>
<div
class=
"submit"
>
确认
</div>
...
...
apps/passport/controllers/captcha.js
View file @
6f3a12e
...
...
@@ -38,6 +38,24 @@ exports.imgCheck = (req, res, next) => {
}).
catch
(
next
);
};
exports
.
imgCheckRisk
=
(
req
,
res
,
next
)
=>
{
if
(
!
req
.
session
.
apiRiskValidate
)
{
return
next
();
}
return
req
.
ctx
(
imgCheckServiceModel
).
getRiskCheckImg
(
req
.
cookies
.
udid
).
then
(
result
=>
{
return
request
({
url
:
result
,
headers
:
{
'X-request-ID'
:
req
.
reqID
||
''
,
'X-YOHO-IP'
:
req
.
yoho
.
clientIp
||
''
,
'X-Forwarded-For'
:
req
.
yoho
.
clientIp
||
''
,
'User-Agent'
:
'yoho/nodejs'
}
}).
pipe
(
res
);
// eslint-disable-line
}).
catch
(
next
);
};
/**
* 验证img-check验证码
*/
...
...
apps/passport/models/imgcheck.js
View file @
6f3a12e
...
...
@@ -2,7 +2,10 @@
const
PAGE
=
'H5'
;
const
logger
=
global
.
yoho
.
logger
;
const
serviceAPI
=
global
.
yoho
.
ServiceAPI
.
ApiUrl
;
const
ApiUrl
=
global
.
yoho
.
API
.
ApiUrl
;
const
config
=
global
.
yoho
.
config
;
const
sign
=
global
.
yoho
.
sign
;
const
querystring
=
require
(
'querystring'
);
module
.
exports
=
class
extends
global
.
yoho
.
BaseModel
{
constructor
(
ctx
)
{
...
...
@@ -57,4 +60,11 @@ module.exports = class extends global.yoho.BaseModel {
return
result
;
});
}
getRiskCheckImg
(
udid
)
{
return
Promise
.
resolve
(
`
$
{
ApiUrl
}
/passport/img
-
verify
?
$
{
querystring
.
stringify
(
sign
.
apiSign
({
udid
,
fromPage
:
PAGE
}))}
`
);
}
};
...
...
apps/passport/router.js
View file @
6f3a12e
...
...
@@ -133,6 +133,7 @@ let captcha = require('./controllers/captcha');
router
.
get
(
'/passport/captcha/get'
,
captcha
.
get
);
router
.
get
(
'/passport/img-check.jpg'
,
captcha
.
imgCheck
);
router
.
get
(
'/passport/img-check-risk.jpg'
,
captcha
.
imgCheckRisk
);
/**
* 注册
...
...
doraemon/middleware/error-handler.js
View file @
6f3a12e
...
...
@@ -13,6 +13,9 @@ const routeEncode = require('./route-encode');
const
pathWhiteList
=
require
(
'./limiter/rules/path-white-list'
);
const
_
=
require
(
'lodash'
);
const
replaceKey
=
'${refer}'
;
const
checkRefer
=
helpers
.
urlFormat
(
'/3party/check'
,
{
refer
:
replaceKey
});
const
forceNoCache
=
(
res
)
=>
{
if
(
res
&&
!
res
.
finished
)
{
res
.
set
({
...
...
@@ -163,35 +166,42 @@ exports.serverError = () => {
refer
:
req
.
originalUrl
}));
}
}
else
if
(
err
.
code
===
9999991
||
err
.
code
===
9999992
)
{
if
(
!
_
.
includes
(
pathWhiteList
(),
req
.
path
))
{
let
remoteIp
=
req
.
yoho
.
clientIp
;
}
else
if
(
err
.
apiRisk
||
err
.
code
===
9999991
||
err
.
code
===
9999992
)
{
if
(
!
err
.
apiRisk
&&
_
.
includes
(
pathWhiteList
(),
req
.
path
))
{
return
_err510
(
req
,
res
,
510
,
err
);
}
const
isHuman
=
await
cache
.
getAsync
(
`
$
{
config
.
app
}
:
limiter
:
api
:
ishuman
:
$
{
remoteIp
}
`
)
;
let
remoteIp
=
req
.
yoho
.
clientIp
;
if
(
!
isHuman
)
{
if
(
remoteIp
.
indexOf
(
','
)
>
0
)
{
let
arr
=
remoteIp
.
split
(
','
);
if
(
remoteIp
.
indexOf
(
','
)
>
0
)
{
let
arr
=
remoteIp
.
split
(
','
);
remoteIp
=
arr
[
0
];
}
cache
.
setAsync
(
`
$
{
config
.
app
}
:
limiter
:
$
{
remoteIp
}
`
,
1
,
config
.
LIMITER_IP_TIME
);
remoteIp
=
arr
[
0
];
}
let
limitAPI
=
helpers
.
urlFormat
(
'/3party/check'
,
{
refer
:
req
.
get
(
'Referer'
)
||
''
});
let
limitPage
=
helpers
.
urlFormat
(
'/3party/check'
,
{
refer
:
req
.
protocol
+
'://'
+
req
.
get
(
'host'
)
+
req
.
originalUrl
});
let
sessionLimitKey
;
let
isHuman
;
if
(
err
.
apiRisk
)
{
sessionLimitKey
=
'apiRiskValidate'
;
}
else
{
sessionLimitKey
=
'apiLimitValidate'
;
isHuman
=
await
cache
.
getAsync
(
`
$
{
config
.
app
}:
limiter
:
api
:
ishuman
:
$
{
remoteIp
}
`
);
}
if
(
!
isHuman
)
{
cache
.
setAsync
(
`
$
{
config
.
app
}
:
limiter
:
$
{
remoteIp
}
`
,
1
,
config
.
LIMITER_IP_TIME
);
req
.
session
.
apiLimitValidate
=
true
;
if
(
req
.
xhr
)
{
return
res
.
status
(
510
).
json
({
code
:
err
.
code
,
data
:
{
refer
:
limitAPI
}
});
}
req
.
session
[
sessionLimitKey
]
=
true
;
return
res
.
redirect
(
limitPage
);
if
(
req
.
xhr
)
{
return
res
.
status
(
510
).
json
({
code
:
err
.
code
,
data
:
{
refer
:
checkRefer
.
replace
(
replaceKey
,
req
.
get
(
'Referer'
)
||
''
)}
});
}
return
res
.
redirect
(
checkRefer
.
replace
(
replaceKey
,
req
.
protocol
+
'://'
+
req
.
get
(
'host'
)
+
req
.
originalUrl
));
}
return
_err510
(
req
,
res
,
510
,
err
);
...
...
doraemon/middleware/limiter/rules/path-white-list.js
View file @
6f3a12e
...
...
@@ -9,6 +9,7 @@ const DEFAULT_PATH_WHITE_LIST = [
'/3party/check/submit'
,
'/passport/captcha/get'
,
'/passport/img-check.jpg'
,
'/passport/img-check-risk.jpg'
,
'/passport/geetest/register'
,
'/activity/individuation'
,
'/activity/individuation/coupon'
,
...
...
public/js/3party/check.page.js
View file @
6f3a12e
require
(
'3party/check.page.css'
);
require
(
'common'
);
// 图片验证码
let
Validate
=
require
(
'plugin/validata'
);
let
$
=
require
(
'yoho-jquery'
),
Validate
=
require
(
'plugin/validata'
);
let
validate
=
new
Validate
(
'#js-img-check'
,
{
let
$check
=
$
(
'#js-img-check'
);
let
baseInfo
=
{
pid
:
window
.
queryString
.
pid
};
let
validateOptions
=
{
useREM
:
{
rootFontSize
:
40
,
picWidth
:
1
5
0
picWidth
:
1
4
0
}
});
};
if
(
$check
.
data
(
'riskimg'
))
{
validateOptions
.
imgSrc
=
'/passport/img-check-risk.jpg'
;
baseInfo
.
apiRiskValidate
=
true
;
}
let
validate
=
new
Validate
(
$check
,
validateOptions
);
validate
.
init
();
$
(
function
()
{
$
(
'.submit'
).
on
(
'click'
,
function
()
{
validate
.
getResults
().
then
((
result
)
=>
{
$
.
extend
(
result
,
{
pid
:
window
.
queryString
.
pid
}
);
$
.
extend
(
result
,
baseInfo
);
$
.
ajax
({
method
:
'POST'
,
...
...
public/js/plugin/img-check.js
View file @
6f3a12e
...
...
@@ -148,8 +148,9 @@ ImgCheck.prototype = {
*/
refresh
:
function
()
{
const
self
=
this
;
const
imgSrc
=
self
.
imgSrc
||
'/passport/img-check.jpg'
;
self
.
render
({
imgSrc
:
`
/
passport
/
img
-
check
.
jpg
?
t
=
$
{
Date
.
now
()}
`
});
self
.
render
({
imgSrc
:
`
$
{
imgSrc
}
?
t
=
$
{
Date
.
now
()}
`
});
},
...
...
public/scss/3party/check.page.css
View file @
6f3a12e
...
...
@@ -2,16 +2,50 @@
.check-page
{
margin
:
20px
auto
;
width
:
700px
;
width
:
590px
;
.wran-tip
{
font-size
:
30px
;
color
:
#444
;
text-align
:
center
;
margin-bottom
:
150px
;
margin-top
:
60px
;
.iconfont
{
font-size
:
110px
;
display
:
block
;
color
:
#bbb
;
}
}
.img-check-header
{
font-size
:
24px
;
}
.img-check-pics
>
li
{
width
:
140px
;
height
:
140px
;
background-size
:
560px
560px
;
position
:
relative
;
&:before
{
content
:
""
;
position
:
absolute
;
width
:
100%
;
height
:
100%
;
box-sizing
:
border-box
;
border
:
1px
solid
#e8e8e8
;
}
}
.submit
{
width
:
100%
;
height
:
100px
;
line-height
:
100px
;
height
:
90px
;
line-height
:
90px
;
text-align
:
center
;
font-size
:
3
2
px
;
font-size
:
3
0
px
;
color
:
#fff
;
background
:
#5cb85c
;
border-radius
:
10px
;
background
:
#444
;
border-radius
:
8px
;
}
}
...
...
Please
register
or
login
to post a comment