def r_sign_in(): args_rules = [ Rules.LOGIN_NAME.value, Rules.PASSWORD.value ] user = User() user.login_name = request.json.get('login_name') user.password = request.json.get('password') try: ji.Check.previewing(args_rules, user.__dict__) plain_password = user.password user.get_by('login_name') if not ji.Security.ji_pbkdf2_check(password=plain_password, password_hash=user.password): ret = dict() ret['state'] = ji.Common.exchange_state(40101) ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 鉴权失败']) raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False)) token = Utils.generate_token(user.id) session['token'] = token rep = make_response() rep.data = json.dumps({'state': ji.Common.exchange_state(20000)}, ensure_ascii=False) return rep except ji.PreviewingError, e: return json.loads(e.message)
def r_after_request(response): try: # https://developer.mozilla.org/en/HTTP_access_control # (中文版) https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials # http://www.w3.org/TR/cors/ # 由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。 if request.referrer is None: # 跑测试脚本时,用该规则。 response.headers['Access-Control-Allow-Origin'] = '*' else: # 生产环境中,如果前后端分离。那么请指定具体的前端域名地址,不要用如下在开发环境中的便捷方式。 # -- Access-Control-Allow-Credentials为true,携带cookie时,不允许Access-Control-Allow-Origin为通配符,是浏览器对用户的一种安全保护。 # -- 至少能避免登录山寨网站,骗取用户相关信息。 response.headers['Access-Control-Allow-Origin'] = '/'.join(request.referrer.split('/')[:3]) response.headers['Access-Control-Allow-Credentials'] = 'true' response.headers['Access-Control-Allow-Methods'] = 'HEAD, GET, POST, DELETE, OPTIONS, PATCH, PUT' response.headers['Access-Control-Allow-Headers'] = 'X-Request-With, Content-Type' response.headers['Access-Control-Expose-Headers'] = 'Set-Cookie' # 少于session生命周期一半时,自动对其续期 if not is_not_need_to_auth(request.endpoint) and hasattr(g, 'token') and \ g.token['exp'] < (ji.Common.ts() + (app.config['token_ttl'] / 2)): token = Utils.generate_token(g.token['uid']) # 清除原有session,由新session代替 for key in session.keys(): session.pop(key=key) session['token'] = token return response except ji.JITError, e: return json.loads(e.message)
def r_send_reset_password_email(login_name): args_rules = [ Rules.LOGIN_NAME.value ] try: ji.Check.previewing(args_rules, {'login_name': login_name}) user = User() try: user.login_name = login_name user.get_by('login_name') except ji.PreviewingError, e: # 如果 login_name 没有找到,则尝试从email里面查找 # 因为用户可能会把登录名理解成email user.email = login_name user.get_by('email') host_url = request.host_url.rstrip('/') # 5 分钟有效期 token = Utils.generate_token(uid=user.id, ttl=300, audience='r_reset_password') reset_password_url = '/'.join([host_url, 'reset_password', token]) smtp_server = ji.NetUtils.smtp_init(host=app.config['smtp_host'], port=app.config.get('smtp_port', None), login_name=app.config['smtp_user'], password=app.config['smtp_password'], tls=app.config['smtp_starttls']) ji.NetUtils.send_mail(smtp_server=smtp_server, sender=app.config['smtp_user'], receivers=[user.email], title=u'重置登录密码', message=u'请复制以下地址到浏览器中打开:' + reset_password_url) ret = dict() ret['state'] = ji.Common.exchange_state(20000) ret['data'] = {'email': user.email} return ret