Showing
7 changed files
with
357 additions
and
49 deletions
@@ -8,7 +8,10 @@ | @@ -8,7 +8,10 @@ | ||
8 | const _ = require('lodash'); | 8 | const _ = require('lodash'); |
9 | const passport = require('passport'); | 9 | const passport = require('passport'); |
10 | const WeixinStrategy = require('passport-weixin'); | 10 | const WeixinStrategy = require('passport-weixin'); |
11 | +const SinaStrategy = require('passport-sina').Strategy; | ||
11 | const LocalStrategy = require('passport-local').Strategy; | 12 | const LocalStrategy = require('passport-local').Strategy; |
13 | +const QQStrategy = require('passport-qq').Strategy; | ||
14 | +const AlipayStrategy = require('./models/passport-alipay').Strategy; | ||
12 | 15 | ||
13 | const md5 = require('md5'); | 16 | const md5 = require('md5'); |
14 | 17 | ||
@@ -18,6 +21,7 @@ const config = global.yoho.config; | @@ -18,6 +21,7 @@ const config = global.yoho.config; | ||
18 | const helpers = global.yoho.helpers; | 21 | const helpers = global.yoho.helpers; |
19 | const cookie = global.yoho.cookie; | 22 | const cookie = global.yoho.cookie; |
20 | const logger = global.yoho.logger; | 23 | const logger = global.yoho.logger; |
24 | +const cache = global.yoho.cache; | ||
21 | 25 | ||
22 | let siteUrl = config.siteUrl.indexOf('//') === 0 ? 'http:' + config.siteUrl : config.siteUrl; | 26 | let siteUrl = config.siteUrl.indexOf('//') === 0 ? 'http:' + config.siteUrl : config.siteUrl; |
23 | 27 | ||
@@ -52,16 +56,63 @@ passport.use(new LocalStrategy({ | @@ -52,16 +56,63 @@ passport.use(new LocalStrategy({ | ||
52 | 56 | ||
53 | let shoppingKey = cookie.getShoppingKey(req); | 57 | let shoppingKey = cookie.getShoppingKey(req); |
54 | 58 | ||
55 | - AuthHelper.signin(area, username, password, shoppingKey).then((result) => { | 59 | + let account = req.body.account; |
60 | + let ip = req.ip; | ||
61 | + | ||
62 | + let errorLoginKey = 'account_errorlogin_' + account; | ||
63 | + let accountKey = 'account_signin_' + account; | ||
64 | + let ipKey = 'ip_signin_' + ip; | ||
65 | + | ||
66 | + let cacheGet = [cache.get(errorLoginKey), cache.get(accountKey), cache.get(ipKey)]; | ||
67 | + | ||
68 | + Promise.all(cacheGet).then(times => { | ||
69 | + let errLoginTimes = parseInt(times[0], 0) || 0; | ||
70 | + let accountTimes = parseInt(times[1], 0) || 0; | ||
71 | + let ipTimes = parseInt(times[2], 0) || 0; | ||
72 | + | ||
73 | + console.log(errLoginTimes); | ||
74 | + | ||
75 | + if (accountTimes >= 10) { | ||
76 | + done('您的账号已被暂时锁定,请稍后再试', null); | ||
77 | + } else if (ipTimes >= 100) { | ||
78 | + done('您尝试的次数过多,账号已被暂时锁定,请稍后再试', null); | ||
79 | + } else { | ||
80 | + return AuthHelper.signin(area, username, password, shoppingKey).then((result) => { | ||
81 | + console.log(result); | ||
56 | if (result.code && result.code === 200 && result.data.uid) { | 82 | if (result.code && result.code === 200 && result.data.uid) { |
83 | + cache.del(errorLoginKey); | ||
84 | + | ||
57 | done(null, result.data); | 85 | done(null, result.data); |
58 | } else { | 86 | } else { |
59 | - done('账号或密码不正确', null); | 87 | + errLoginTimes = errLoginTimes + 1; |
88 | + accountTimes = accountTimes + 1; | ||
89 | + ipTimes = ipTimes + 1; | ||
90 | + cache.set(errorLoginKey, errLoginTimes); | ||
91 | + cache.set(accountKey, accountTimes, 1800); | ||
92 | + cache.set(ipKey, ipTimes, 3600); | ||
93 | + | ||
94 | + //再次校验 | ||
95 | + if (ipTimes >= 100) { | ||
96 | + done('您尝试的次数过多,账号已被暂时锁定,请稍后再试', null); | ||
97 | + } else if (accountTimes >= 10) { | ||
98 | + done('您的账号已被暂时锁定,请稍后再试', null); | ||
99 | + } else if (errLoginTimes >= 3) { | ||
100 | + done(`您输入的密码及账户名不匹配, | ||
101 | + 是否<a href="${helpers.urlFormat('/passport/back/index')}" target="_blank">忘记密码?</a>`, | ||
102 | + { needCaptcha: true }); | ||
103 | + } else { | ||
104 | + done(`您输入的密码及账户名不匹配, | ||
105 | + 是否<a href="${helpers.urlFormat('/passport/back/index')}" target="_blank">忘记密码?</a>`, | ||
106 | + { needCaptcha: false }); | ||
107 | + } | ||
108 | + } | ||
109 | + }); | ||
60 | } | 110 | } |
61 | }).catch(e => { | 111 | }).catch(e => { |
62 | logger.error('call the signin service fail,', e); | 112 | logger.error('call the signin service fail,', e); |
63 | done('登录失败,请稍后重试', null); | 113 | done('登录失败,请稍后重试', null); |
64 | }); | 114 | }); |
115 | + | ||
65 | })); | 116 | })); |
66 | 117 | ||
67 | /** | 118 | /** |
@@ -74,6 +125,35 @@ passport.use('wechat', new WeixinStrategy({ | @@ -74,6 +125,35 @@ passport.use('wechat', new WeixinStrategy({ | ||
74 | callbackURL: `${siteUrl}/passport/login/wechat/callback`, | 125 | callbackURL: `${siteUrl}/passport/login/wechat/callback`, |
75 | requireState: true, | 126 | requireState: true, |
76 | scope: 'snsapi_login' | 127 | scope: 'snsapi_login' |
77 | -}, function(accessToken, refreshToken, profile, done) { | 128 | +}, (accessToken, refreshToken, profile, done) => { |
129 | + done(null, profile); | ||
130 | +})); | ||
131 | + | ||
132 | +// sina 登录 | ||
133 | +passport.use('sina', new SinaStrategy({ | ||
134 | + clientID: '3739328910', | ||
135 | + clientSecret: '9d44cded26d048e23089e5e975c93df1', | ||
136 | + callbackURL: `${siteUrl}/passport/login/sina/callback`, | ||
137 | + requireState: false | ||
138 | +}, (accessToken, refreshToken, profile, done) => { | ||
78 | done(null, profile); | 139 | done(null, profile); |
79 | })); | 140 | })); |
141 | + | ||
142 | +// qq 登录 | ||
143 | +passport.use('qq', new QQStrategy({ | ||
144 | + clientID: '100229394', | ||
145 | + clientSecret: 'c0af9c29e0900813028c2ccb42021792', | ||
146 | + callbackURL: `${siteUrl}/passport/login/qq/callback`, | ||
147 | + requireState: false | ||
148 | +}, (accessToken, refreshToken, profile, done) => { | ||
149 | + done(null, profile); | ||
150 | +})); | ||
151 | + | ||
152 | +// alipay 登录 | ||
153 | +passport.use('alipay', new AlipayStrategy({ | ||
154 | + partner: '2088701661478015', | ||
155 | + key: 'kcxawi9bb07mzh0aq2wcirsf9znusobw', | ||
156 | + callbackURL: `${siteUrl}/passport/login/alipay/callback` | ||
157 | +}), (profile, done) => { | ||
158 | + done(null, profile); | ||
159 | +}); |
@@ -21,7 +21,7 @@ const loginPage = `${config.siteUrl}/passport/login/index`; | @@ -21,7 +21,7 @@ const loginPage = `${config.siteUrl}/passport/login/index`; | ||
21 | const SIGNIN_LEFT_BANNER_CODE = 'db350894e01e90eac55cd3a13ad77331'; | 21 | const SIGNIN_LEFT_BANNER_CODE = 'db350894e01e90eac55cd3a13ad77331'; |
22 | 22 | ||
23 | // 第三方登录回调 | 23 | // 第三方登录回调 |
24 | -function doPassportCallback(req, res, next, user) { | 24 | +function doPassportCallback(req, res, user) { |
25 | let shoppingKey = cookie.getShoppingKey(req); | 25 | let shoppingKey = cookie.getShoppingKey(req); |
26 | let refer = req.cookies.refer; | 26 | let refer = req.cookies.refer; |
27 | 27 | ||
@@ -60,7 +60,7 @@ function doPassportCallback(req, res, next, user) { | @@ -60,7 +60,7 @@ function doPassportCallback(req, res, next, user) { | ||
60 | } else if (result.code === 200 && result.data.uid) { | 60 | } else if (result.code === 200 && result.data.uid) { |
61 | return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => { | 61 | return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => { |
62 | return refer; | 62 | return refer; |
63 | - }).catch(next); | 63 | + }); |
64 | } | 64 | } |
65 | }).then((redirectTo) => { | 65 | }).then((redirectTo) => { |
66 | res.redirect(redirectTo); | 66 | res.redirect(redirectTo); |
@@ -83,26 +83,6 @@ const common = { | @@ -83,26 +83,6 @@ const common = { | ||
83 | domain: 'yohobuy.com' | 83 | domain: 'yohobuy.com' |
84 | }); | 84 | }); |
85 | next(); | 85 | next(); |
86 | - }, | ||
87 | - ipFilter: (req, res, next) => { | ||
88 | - let account = req.body.account; | ||
89 | - let ip = req.ip; | ||
90 | - | ||
91 | - // let errorLoginKey = 'account_errorlogin_' + account; | ||
92 | - let accountKey = 'account_signin_' + account; | ||
93 | - let ipKey = 'ip_signin_' + ip; | ||
94 | - | ||
95 | - // let errLoginTimes = cache.get(errorLoginKey) || 0; | ||
96 | - let accountTimes = cache.get(accountKey) || 0; | ||
97 | - let ipTimes = cache.get(ipKey) || 0; | ||
98 | - | ||
99 | - if (accountTimes >= 10) { | ||
100 | - res.json({ code: 400, message: '您的账号已被暂时锁定,请稍后再试', data: '' }); | ||
101 | - } else if (ipTimes >= 100) { | ||
102 | - res.json({ code: 400, message: '您尝试的次数过多,账号已被暂时锁定,请稍后再试', data: '' }); | ||
103 | - } else { | ||
104 | - return next(); | ||
105 | - } | ||
106 | } | 86 | } |
107 | }; | 87 | }; |
108 | 88 | ||
@@ -135,6 +115,7 @@ const local = { | @@ -135,6 +115,7 @@ const local = { | ||
135 | forgetPwd: helpers.urlFormat('/passport/back/index'), | 115 | forgetPwd: helpers.urlFormat('/passport/back/index'), |
136 | fastReg: helpers.urlFormat('/reg.html'), | 116 | fastReg: helpers.urlFormat('/reg.html'), |
137 | weixinLogin: helpers.urlFormat('/passport/autosign/wechat'), | 117 | weixinLogin: helpers.urlFormat('/passport/autosign/wechat'), |
118 | + qqLogin: helpers.urlFormat('/passport/autosign/qq'), | ||
138 | weiboLogin: helpers.urlFormat('/passport/autosign/sina'), | 119 | weiboLogin: helpers.urlFormat('/passport/autosign/sina'), |
139 | alipayLogin: helpers.urlFormat('/passport/autosign/alipay'), | 120 | alipayLogin: helpers.urlFormat('/passport/autosign/alipay'), |
140 | doubanLogin: helpers.urlFormat('/passport/autosign/douban'), | 121 | doubanLogin: helpers.urlFormat('/passport/autosign/douban'), |
@@ -153,11 +134,20 @@ const local = { | @@ -153,11 +134,20 @@ const local = { | ||
153 | res.json({ | 134 | res.json({ |
154 | code: 400, | 135 | code: 400, |
155 | message: err, | 136 | message: err, |
156 | - data: '' | 137 | + data: user || {} |
157 | }); | 138 | }); |
158 | } else { | 139 | } else { |
140 | + let isRemember = req.body.isRemember; | ||
159 | let refer = req.cookies.refer; | 141 | let refer = req.cookies.refer; |
160 | 142 | ||
143 | + if (isRemember) { | ||
144 | + AuthHelper.rememberAccount({ | ||
145 | + area: req.body.areaCode || '86', | ||
146 | + account: req.body.account, | ||
147 | + password: req.body.password | ||
148 | + }, req, res); | ||
149 | + } | ||
150 | + | ||
161 | if (refer) { | 151 | if (refer) { |
162 | refer = decodeURI(req.cookies.refer); | 152 | refer = decodeURI(req.cookies.refer); |
163 | } else { | 153 | } else { |
@@ -177,33 +167,142 @@ const local = { | @@ -177,33 +167,142 @@ const local = { | ||
177 | }); | 167 | }); |
178 | } | 168 | } |
179 | })(req, res, next); | 169 | })(req, res, next); |
170 | + }, | ||
171 | + logout: (req, res) => { | ||
172 | + req.session = null; | ||
173 | + | ||
174 | + res.clearCookie('_UID', { | ||
175 | + domain: 'yohobuy.com' | ||
176 | + }); | ||
177 | + res.clearCookie('_TOKEN', { | ||
178 | + domain: 'yohobuy.com' | ||
179 | + }); | ||
180 | + res.clearCookie('_SPK'); | ||
181 | + res.clearCookie('_g'); | ||
182 | + res.clearCookie('isRemember'); | ||
183 | + res.clearCookie('remem'); | ||
184 | + let refer = req.get('Referer') || config.siteUrl; | ||
185 | + | ||
186 | + res.redirect(refer); | ||
180 | } | 187 | } |
181 | }; | 188 | }; |
182 | 189 | ||
183 | const wechat = { | 190 | const wechat = { |
184 | login: (req, res, next) => { | 191 | login: (req, res, next) => { |
192 | + req.session = req.session || {}; | ||
193 | + req.session.authState = uuid.v4(); | ||
185 | return passport.authenticate('wechat', { | 194 | return passport.authenticate('wechat', { |
186 | - state: uuid.v4() | 195 | + state: req.session.authState |
187 | })(req, res, next); | 196 | })(req, res, next); |
188 | }, | 197 | }, |
189 | callback: (req, res, next) => { | 198 | callback: (req, res, next) => { |
199 | + if (req.session && req.session.authState && req.session.authState === req.query.state) { | ||
190 | passport.authenticate('wechat', (err, user) => { | 200 | passport.authenticate('wechat', (err, user) => { |
191 | if (err) { | 201 | if (err) { |
192 | log.error(`wechat authenticate error : ${JSON.stringify(err)}`); | 202 | log.error(`wechat authenticate error : ${JSON.stringify(err)}`); |
193 | return res.redirect(loginPage); | 203 | return res.redirect(loginPage); |
194 | } | 204 | } |
195 | 205 | ||
196 | - doPassportCallback(req, res, next, { | 206 | + doPassportCallback(req, res, { |
197 | openId: user._json.openid, | 207 | openId: user._json.openid, |
198 | unionId: user._json.unionid || user.id, | 208 | unionId: user._json.unionid || user.id, |
199 | nickname: user._json.nickname || user.displayName, | 209 | nickname: user._json.nickname || user.displayName, |
200 | sourceType: 'wechat', | 210 | sourceType: 'wechat', |
201 | rawUser: user | 211 | rawUser: user |
202 | - }); | 212 | + }).catch(next); |
203 | })(req, res, next); | 213 | })(req, res, next); |
214 | + } else { | ||
215 | + return next(new Error('Auth State Mismatch')); | ||
216 | + } | ||
204 | } | 217 | } |
205 | }; | 218 | }; |
206 | 219 | ||
220 | +const sina = { | ||
221 | + login: (req, res, next) => { | ||
222 | + req.session = req.session || {}; | ||
223 | + req.session.authState = uuid.v4(); | ||
224 | + return passport.authenticate('sina', { | ||
225 | + state: req.session.authState | ||
226 | + })(req, res, next); | ||
227 | + }, | ||
228 | + callback: (req, res, next) => { | ||
229 | + if (req.session && req.session.authState && req.session.authState === req.query.state) { | ||
230 | + passport.authenticate('sina', (err, user) => { | ||
231 | + if (err) { | ||
232 | + log.error(`sina authenticate error : ${JSON.stringify(err)}`); | ||
233 | + return res.redirect(loginPage); | ||
234 | + } | ||
235 | + let nickname = user.screen_name; | ||
236 | + let openId = user.id; | ||
237 | + | ||
238 | + doPassportCallback(req, res, { | ||
239 | + openId: openId, | ||
240 | + nickname: nickname, | ||
241 | + sourceType: 'sina' | ||
242 | + }).catch(next); | ||
243 | + })(req, res, next); | ||
244 | + } else { | ||
245 | + return next(new Error('Auth State Mismatch')); | ||
246 | + } | ||
247 | + } | ||
248 | +}; | ||
249 | + | ||
250 | +const qq = { | ||
251 | + login: (req, res, next) => { | ||
252 | + req.session = req.session || {}; | ||
253 | + req.session.authState = uuid.v4(); | ||
254 | + return passport.authenticate('qq', { | ||
255 | + state: req.session.authState | ||
256 | + })(req, res, next); | ||
257 | + }, | ||
258 | + callback: (req, res, next) => { | ||
259 | + if (req.session && req.session.authState && req.session.authState === req.query.state) { | ||
260 | + passport.authenticate('qq', (err, user) => { | ||
261 | + if (err) { | ||
262 | + log.error(`qq authenticate error : ${JSON.stringify(err)}`); | ||
263 | + return res.redirect(loginPage); | ||
264 | + } | ||
265 | + let nickname = user.nickname; | ||
266 | + let openId = user.openid; | ||
267 | + | ||
268 | + doPassportCallback(req, res, { | ||
269 | + openId: openId, | ||
270 | + nickname: nickname, | ||
271 | + sourceType: 'qq' | ||
272 | + }).catch(next); | ||
273 | + })(req, res, next); | ||
274 | + } else { | ||
275 | + return next(new Error('Auth State Mismatch')); | ||
276 | + } | ||
277 | + } | ||
278 | +}; | ||
279 | + | ||
280 | +const alipay = { | ||
281 | + login: (req, res, next) => { | ||
282 | + return passport.authenticate('alipay')(req, res, next); | ||
283 | + }, | ||
284 | + callback: (req, res, next) => { | ||
285 | + passport.authenticate('alipay', (err, user) => { | ||
286 | + if (err) { | ||
287 | + log.error(`alipay authenticate error : ${JSON.stringify(err)}`); | ||
288 | + return res.redirect(loginPage); | ||
289 | + } | ||
290 | + let nickname = user.realName; | ||
291 | + let openId = user.userId; | ||
292 | + | ||
293 | + doPassportCallback(req, res, { | ||
294 | + openId: openId, | ||
295 | + nickname: nickname, | ||
296 | + sourceType: 'alipay' | ||
297 | + }).catch(next); | ||
298 | + })(req, res, next); | ||
299 | + } | ||
300 | +}; | ||
301 | + | ||
302 | + | ||
207 | exports.common = common; | 303 | exports.common = common; |
208 | exports.wechat = wechat; | 304 | exports.wechat = wechat; |
209 | exports.local = local; | 305 | exports.local = local; |
306 | +exports.sina = sina; | ||
307 | +exports.qq = qq; | ||
308 | +exports.alipay = alipay; |
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | +const md5 = require('md5'); | ||
4 | + | ||
5 | +const cache = global.yoho.cache; | ||
3 | const sign = global.yoho.sign; | 6 | const sign = global.yoho.sign; |
4 | const api = global.yoho.API; | 7 | const api = global.yoho.API; |
5 | 8 | ||
6 | -class Auth { | ||
7 | - | ||
8 | - static signin(area, profile, password, shoppingKey) { | 9 | +const Auth = { |
10 | + signin(area, profile, password, shoppingKey) { | ||
9 | let param = { | 11 | let param = { |
10 | method: 'app.passport.signin', | 12 | method: 'app.passport.signin', |
11 | area: area, | 13 | area: area, |
@@ -18,9 +20,8 @@ class Auth { | @@ -18,9 +20,8 @@ class Auth { | ||
18 | } | 20 | } |
19 | 21 | ||
20 | return api.post('', param); | 22 | return api.post('', param); |
21 | - } | ||
22 | - | ||
23 | - static signinByOpenID(nickname, openId, sourceType, shoppingKey) { | 23 | + }, |
24 | + signinByOpenID(nickname, openId, sourceType, shoppingKey) { | ||
24 | let param = { | 25 | let param = { |
25 | nickname: nickname, | 26 | nickname: nickname, |
26 | openId: openId, | 27 | openId: openId, |
@@ -33,9 +34,8 @@ class Auth { | @@ -33,9 +34,8 @@ class Auth { | ||
33 | } | 34 | } |
34 | 35 | ||
35 | return api.get('', param); | 36 | return api.get('', param); |
36 | - } | ||
37 | - | ||
38 | - static signinByWechat(nickname, openId, unionId, sourceType, shoppingKey) { | 37 | + }, |
38 | + signinByWechat(nickname, openId, unionId, sourceType, shoppingKey) { | ||
39 | let param = { | 39 | let param = { |
40 | nickname: nickname, | 40 | nickname: nickname, |
41 | openId: openId, | 41 | openId: openId, |
@@ -49,24 +49,22 @@ class Auth { | @@ -49,24 +49,22 @@ class Auth { | ||
49 | } | 49 | } |
50 | 50 | ||
51 | return api.get('', param); | 51 | return api.get('', param); |
52 | - } | ||
53 | - | ||
54 | - static profile(uid) { | 52 | + }, |
53 | + profile(uid) { | ||
55 | let param = { | 54 | let param = { |
56 | uid: uid, | 55 | uid: uid, |
57 | method: 'app.passport.profile' | 56 | method: 'app.passport.profile' |
58 | }; | 57 | }; |
59 | 58 | ||
60 | return api.get('', param); | 59 | return api.get('', param); |
61 | - } | ||
62 | - | ||
63 | - static syncUserSession(uid, req, res) { | 60 | + }, |
61 | + syncUserSession(uid, req, res) { | ||
64 | return Auth.profile(uid).then((userInfo) => { | 62 | return Auth.profile(uid).then((userInfo) => { |
65 | let token = sign.makeToken(uid); | 63 | let token = sign.makeToken(uid); |
66 | let data = userInfo.data; | 64 | let data = userInfo.data; |
67 | 65 | ||
68 | if (data) { | 66 | if (data) { |
69 | - let uidCookie = `${data.profile_name}::${data.uid}::${data.vip_info.title}::${token}`; | 67 | + let uidCookie = `{data.profile_name}::${data.uid}::${data.vip_info.title}::${token}`; |
70 | 68 | ||
71 | req.session._TOKEN = token; | 69 | req.session._TOKEN = token; |
72 | req.session._LOGIN_UID = uid; | 70 | req.session._LOGIN_UID = uid; |
@@ -80,8 +78,18 @@ class Auth { | @@ -80,8 +78,18 @@ class Auth { | ||
80 | res.cookie('_TOKEN', token, { | 78 | res.cookie('_TOKEN', token, { |
81 | domain: 'yohobuy.com' | 79 | domain: 'yohobuy.com' |
82 | }); // esline-disable-line | 80 | }); // esline-disable-line |
83 | - }); | 81 | + }).catch(console.log); |
82 | + }, | ||
83 | + rememberAccount(accountInfo, req, res) { | ||
84 | + let aWeek = (new Date()).getTime() / 1000 + 504000; //504000-一周 | ||
85 | + let rememKey = md5(md5(accountInfo.account + accountInfo.password + accountInfo.area)); | ||
86 | + | ||
87 | + res.cookie('isRemember', true, aWeek); | ||
88 | + res.cookie('remem', rememKey, aWeek); | ||
89 | + if (!cache.get(rememKey)) { | ||
90 | + cache.set(rememKey, accountInfo, aWeek); | ||
91 | + } | ||
84 | } | 92 | } |
85 | -} | 93 | +}; |
86 | 94 | ||
87 | module.exports = Auth; | 95 | module.exports = Auth; |
apps/passport/models/passport-alipay.js
0 → 100644
1 | +/** | ||
2 | + * passport.js 支付宝登录插件 | ||
3 | + * | ||
4 | + * @author JiangFeng<jeff.jiang@yoho.cn> | ||
5 | + * @date 2016/06/21 | ||
6 | + */ | ||
7 | + | ||
8 | +'use strict'; | ||
9 | +const util = require('util'); | ||
10 | +const _ = require('lodash'); | ||
11 | +const md5 = require('md5'); | ||
12 | +const passport = require('passport-strategy'); | ||
13 | + | ||
14 | +// 支付宝网关地址 | ||
15 | +const ALIPAY_URL = 'https://mapi.alipay.com/gateway.do'; | ||
16 | + | ||
17 | +const defaultOptions = { | ||
18 | + service: 'alipay.auth.authorize', | ||
19 | + _input_charset: 'utf-8', | ||
20 | + sign_type: 'MD5', | ||
21 | + target_service: 'user.auth.quick.login' | ||
22 | +}; | ||
23 | + | ||
24 | +/** | ||
25 | + * 将参数排序,拼接成 "参数=参数值" 的格式 | ||
26 | + * | ||
27 | + * @param {Object} params | ||
28 | + */ | ||
29 | +function paramsToRaw(params) { | ||
30 | + let keys = Object.keys(params); | ||
31 | + | ||
32 | + keys = keys.sort(); | ||
33 | + let string = ''; | ||
34 | + | ||
35 | + keys.forEach((key) => { | ||
36 | + string += '&' + key + '=' + params[key]; | ||
37 | + }); | ||
38 | + | ||
39 | + string = string.substr(1); | ||
40 | + return string; | ||
41 | +} | ||
42 | + | ||
43 | +function AlipayStrategy(options, verify) { | ||
44 | + if (typeof options === 'function') { | ||
45 | + verify = options; | ||
46 | + } | ||
47 | + passport.Strategy.call(this); | ||
48 | + this.name = 'alipay'; | ||
49 | + this._verify = verify; | ||
50 | +} | ||
51 | + | ||
52 | +util.inherits(AlipayStrategy, passport.Strategy); | ||
53 | + | ||
54 | +AlipayStrategy.prototype.authenticate = function(req, options) { | ||
55 | + | ||
56 | + if (req.query && req.query.is_success && req.query.sign && req.query.sign_type) { | ||
57 | + let query = req.query; | ||
58 | + let sign = query.sign; | ||
59 | + let signType = query.sign_type; | ||
60 | + | ||
61 | + delete query.sign_type; | ||
62 | + delete query.sign; | ||
63 | + let signString = paramsToRaw(query) + options.key; | ||
64 | + | ||
65 | + if (signType === 'MD5' && sign !== md5(signString)) { | ||
66 | + this.error('alipay callback sign check fail'); | ||
67 | + this.fail('alipay callback sign check fail'); | ||
68 | + return; | ||
69 | + } | ||
70 | + | ||
71 | + if (req.query.is_success === 'T') { | ||
72 | + let user = { | ||
73 | + userId: req.query.user_id, | ||
74 | + realName: req.query.realName, | ||
75 | + email: req.query.email | ||
76 | + }; | ||
77 | + this.success(user, null); | ||
78 | + } else { | ||
79 | + this.error('alipay login fail'); | ||
80 | + this.fail(req.error_code); | ||
81 | + } | ||
82 | + } else { | ||
83 | + let params = _.assign(defaultOptions, options); | ||
84 | + let signType = params.sign_type; | ||
85 | + | ||
86 | + delete params.sign_type; | ||
87 | + delete params.sign; | ||
88 | + let signString = paramsToRaw(params) + options.key; | ||
89 | + | ||
90 | + if (signType === 'MD5') { | ||
91 | + params.sign = md5(signString); | ||
92 | + params.sign_type = 'MD5'; | ||
93 | + } | ||
94 | + this.redirect(ALIPAY_URL + '?' + paramsToRaw(params)); | ||
95 | + } | ||
96 | +}; | ||
97 | + | ||
98 | +exports = module.exports = AlipayStrategy; | ||
99 | + | ||
100 | +exports.Strategy = AlipayStrategy; | ||
101 | + |
@@ -16,11 +16,27 @@ const reg = require(cRoot + '/reg'); | @@ -16,11 +16,27 @@ const reg = require(cRoot + '/reg'); | ||
16 | 16 | ||
17 | const router = express.Router(); // eslint-disable-line | 17 | const router = express.Router(); // eslint-disable-line |
18 | 18 | ||
19 | - | 19 | +// 本地登录 |
20 | router.get('/login', login.common.beforeLogin, login.local.loginPage); | 20 | router.get('/login', login.common.beforeLogin, login.local.loginPage); |
21 | +router.post('/login/auth', login.local.login); | ||
22 | +router.get('/logout', login.local.logout); | ||
23 | + | ||
24 | +// 微信登录 | ||
21 | router.get('/autosign/wechat', login.common.beforeLogin, login.wechat.login); // 微信登录, 兼容 PHP 的路径 | 25 | router.get('/autosign/wechat', login.common.beforeLogin, login.wechat.login); // 微信登录, 兼容 PHP 的路径 |
22 | router.get('/login/wechat/callback', login.wechat.callback); | 26 | router.get('/login/wechat/callback', login.wechat.callback); |
23 | 27 | ||
28 | +// sina登录 | ||
29 | +router.get('/autosign/sina', login.common.beforeLogin, login.sina.login); | ||
30 | +router.get('/login/sina/callback', login.sina.callback); | ||
31 | + | ||
32 | +// qq登录 | ||
33 | +router.get('/autosign/qq', login.common.beforeLogin, login.qq.login); | ||
34 | +router.get('/login/qq/callback', login.qq.callback); | ||
35 | + | ||
36 | +// alipay登录 | ||
37 | +router.get('/autosign/alipay', login.common.beforeLogin, login.alipay.login); | ||
38 | +router.get('/login/alipay/callback', login.alipay.callback); | ||
39 | + | ||
24 | /** | 40 | /** |
25 | * 注册页面路由 | 41 | * 注册页面路由 |
26 | */ | 42 | */ |
@@ -47,6 +47,9 @@ | @@ -47,6 +47,9 @@ | ||
47 | "oneapm": "^1.2.20", | 47 | "oneapm": "^1.2.20", |
48 | "passport": "^0.3.2", | 48 | "passport": "^0.3.2", |
49 | "passport-local": "^1.0.0", | 49 | "passport-local": "^1.0.0", |
50 | + "passport-qq": "0.0.3", | ||
51 | + "passport-sina": "^0.1.0", | ||
52 | + "passport-strategy": "1.x.x", | ||
50 | "passport-weixin": "^0.1.0", | 53 | "passport-weixin": "^0.1.0", |
51 | "request-promise": "^3.0.0", | 54 | "request-promise": "^3.0.0", |
52 | "serve-favicon": "^2.3.0", | 55 | "serve-favicon": "^2.3.0", |
@@ -102,6 +102,7 @@ function syncLoginInfo() { | @@ -102,6 +102,7 @@ function syncLoginInfo() { | ||
102 | expires: -1 | 102 | expires: -1 |
103 | }); | 103 | }); |
104 | } | 104 | } |
105 | + $loginBox.show(); | ||
105 | }); | 106 | }); |
106 | } | 107 | } |
107 | 108 | ||
@@ -530,4 +531,4 @@ function actionCover() { | @@ -530,4 +531,4 @@ function actionCover() { | ||
530 | } | 531 | } |
531 | } | 532 | } |
532 | 533 | ||
533 | -actionCover(); | 534 | +// actionCover(); |
-
Please register or login to post a comment