def set_password(self, password): """ 修改密码, 同时修改所有关联帐号的密码 @param password 新密码 @return [users] """ hash = auth.encode_password(password) plain_password = auth.encode_plain_password(password) username_prefix = self.phone_number + ('js' if self.type == 3 else 'xs') with db.user as c: users = c.auth_user.filter(username__startswith=username_prefix, type=self.type)[:] if users: user_ids = [u.id for u in users] c.auth_user.filter(id__in=user_ids).update(password=hash) c.auth_profile.filter(user_id__in=user_ids).update(password=plain_password) self.auser.password = hash self.password = hash if self.aprofile: self.aprofile.password = plain_password # 更新缓存 for user in users: user.password = hash cache.auth_user.set(user.id, user) if self.aprofile: cache.auth_profile.set(user.id, self.aprofile) else: cache.auth_profile.delete(user.id) return users
def import_user(user_type, phone_number, real_name, gender=1, join_unit_id=0, subject_id=0, sn_code='', send_pwd=0): """ 导入用户资料, 如果是短信开通则open_option="open",如果验证码开通sn_code不能为空,二者选其一 ------------------------------------------- 徐威 2015-03-22 王晨光 2017-06-06 ------------------------------------------- :param user_type: 用户类型 1学生 3老师 :param phone_number: 手机号 :param real_name: 姓名 :param join_unit_id: 要加入的班级ID :param sn_code: 二次短信验证码 :param subject_id: 开通学科ID subject_id 和 sn_code 都为空则暂不开通 :param send_pwd: 是否发送帐号密码 1是 0否 :return: (新用户ID, error) """ username = find_a_username(user_type, phone_number) nowt = int(time.time()) password = "".join(random.sample('1234567890', 6)) # 随机生成6位密码 # 创建auth_user if db.user.auth_user.filter(username=username).exists(): return None, u"用户已存在" user_id = db.user.auth_user.create( username=username, password=auth.encode_password(password), type=user_type, real_name=real_name, date_joined=nowt, status=1, sid=0, grade_id=0, phone=phone_number, platform_id=1 ) db.user.auth_profile.create( user_id=user_id, nickname=real_name, sex=1, password=auth.encode_plain_password(password) ) if not user_id: return None, u"用户已存在" user = db.user.auth_user.get(id=user_id) # 加入班级 join_unit_class_by_id(user, join_unit_id) # 是否发送账号密码 if send_pwd: send_password([user_id]) return user_id, None
def phone_login(request): """ @api {post} /account/login/web [登录]WEB登录 @apiGroup account @apiParamExample {json} 请求示例 { "username":"******", "password":"******", "pass_flag": 1 # 0 以前的老接口,不加密, 1 现在的新程序,加密 } @apiParam {String} username 手机号或帐号 @apiParam {String} password 密码 @apiSuccessExample {json} 成功返回 { "next": "", "error": "", "message": "", "data": [ { "real_name": "张三", "school_name": "创恒中学", "unit_name": "100班", "type":1, "portrait": "头像", "tbkt_token": "有效期7天的token" }, ], "response": "ok" } * type = 1 学生 * type = 3 教师 """ args = request.QUERY.casts(username=str, password=str, pass_flag=int) username = args.username or '' password = args.password or '' pass_flag = int(args.pass_flag or 0) username = username.strip().lower() out = [] if not username: return ajax.jsonp_fail(request, message='请输入用户名或手机号') if not password: return ajax.jsonp_fail(request, message='请输入密码') if pass_flag: password = auth.safe_pass_decode(password) # 模糊匹配(根据手机号+密码猜测具体帐号) if username.isdigit(): encoded_password = auth.encode_plain_password(password) sql = """ select u.username, u.status from auth_user u inner join auth_profile p on p.user_id=u.id and p.password='******' where u.phone='%s' """ % (encoded_password, username) binds = db.user_slave.fetchall_dict(sql) if not binds: return ajax.jsonp_fail(request, message="账号或密码错误!") now_binds = [b for b in binds if int(b.status) != 2] if not now_binds: return ajax.jsonp_fail(request, message="该账号已被禁用,请联系客服") else: user, auth_user = com_user.authenticate(username=username, password=password) if not user: return ajax.jsonp_fail(request, message='账号或密码错误,是否找回密码?') if int(user.status) == 2: return ajax.jsonp_fail(request, message='该账号已被禁用,请联系客服') # 登录检查 error = com_user.web_login_check(user) if error: return ajax.jsonp_fail(request, message=error) # 登录日志 thread_pool.call(common.login_handle, request, args, user) # 输入后缀xs,js 准确返回用户信息 if not username.isdigit(): d = dict( real_name=user.real_name, school_name=user.school_name if user.school_name else "", unit_name=user.unit.name if user.unit else "", portrait=user.portrait, type=user.type, tbkt_token=auth.login(request, user.id), dept_id=user.dept_id, ) out.append(d) return ajax.jsonp_ok(request, out) # 手机号下的所有账号 sql = """ select u.id, u.real_name, p.portrait, u.type,p.password,u.sid,u.dept_id, u.status from auth_user u inner join auth_profile p on u.id = p.user_id and u.phone = "%s" where u.type in (1,3) and u.dept_id in (1,2) and u.status != 2 order by u.type desc """ % username users = db.user_slave.fetchall_dict(sql) if not users: return ajax.jsonp_fail(request, message='账号或密码错误,是否找回密码?') user_ids = [i.id for i in users] regions = db.ketang.mobile_order_region.select("school_name", "unit_class_id", "user_id") \ .filter(user_id__in=user_ids).group_by("user_id")[:] units_id = [i.unit_class_id for i in regions] region_map = {i.user_id: i for i in regions} units = db.slave.school_unit_class.select("unit_name", "id").filter(id__in=units_id)[:] units_map = {i.id: i.unit_name for i in units} for i in users: region = region_map.get(i.id) unit_id = region.unit_class_id if region else 0 school_name = region.school_name if region else "" unit_name = units_map.get(unit_id, "") d = dict( real_name=i.real_name, school_name=school_name, unit_name=unit_name, type=i.type, portrait=get_portrait(i, i.type), # 'portrait': com_user.get_portrait(u, u.type), tbkt_token=create_token(i.id), sid=i.sid, dept_id=i.dept_id ) out.append(d) return ajax.jsonp_ok(request, out)
def p_login(request, role): """ @api {post} /account/login/? [登录]登录 @apiGroup account @apiParamExample {json} 请求示例 /account/login/s 学生登录 /account/login/t 老师登录 { "username":"******", "password":"******", "pass_flag": 1 # 0 以前的老接口,不加密, 1 现在的新程序,加密 "login_type": 90, # 登录类型 1是网站 其他是手机APP "version": "6.0.1", "name": "865f8521b18fe9b", "model": "MI 4LTE", "platform": "Android", "uuid": "A100005064E391", "appversion": "1.0.0" } @apiParam {String} username 手机号或帐号 @apiParam {String} password 密码 @apiParam {Integer} login_type (可选)登录类型 88:Android教辅学生 90:Android教辅教师 89:IOS教辅学生 91:IOS教辅教师 @apiParam {String} version (可选)系统版本号 @apiParam {String} name (可选)设备名称 @apiParam {String} model (可选)手机型号 @apiParam {String} platform (可选)平台名称 @apiParam {String} uuid (可选)设备序列号 @apiParam {String} appversion (可选)app版本 @apiSuccessExample {json} 成功返回 { "next": "", "error": "", "message": "", "tbkt_token": "eHl3dHR3PHF0eHh5dXlzcnY8cXR4eHF4dHVwdQ", "app_version": { "h5": 0, "api": 1, "must": 0 }, "data": "", "response": "ok" } 登录成功后, 服务器会在响应头中添加 Tbkt-Token: xxxx 头域, 分配给客户端一个token. 客户端应记录这个 tbkt_token 并在之后的请求中带上 Tbkt-Token: xxxx 到时如果服务器没有收到 tbkt_token 或者 tbkt_token 过期(7天), 则返回: { "message": "请您先登录", "next": "", "data": "", "response": "fail", "error": "no_user" } 其他请求也要看下响应头里有没有给新token, 有就更新token. 检测新版本机制: 客户端每个请求头加一个 App-Type: 9安卓学生 10安卓教师 11苹果学生 12苹果教师 13 H5学生 14 H5教师 服务器返回头会加一个 App-Version: {"h5": H5版本号, "api": 客户端版本号, "must": 0不强制升级客户端 1强制升级客户端} @apiSuccessExample {json} 失败返回 {"message": "帐号或密码错误", "error": "", "data": "", "response": "fail", "next": ""} 如果error=switch就进入切换身份页面让他选角色 @apiSuccessExample {json} Python示例 import requests r = requests.post('http://127.0.0.1:4000/account/login/t', params={'username':'******', 'password':'******'}) cookies = r.cookies r = requests.post('http://127.0.0.1:4000/class/getpwd', params={'bind_id':'4210824'}, cookies=cookies) print r.json() @apiSuccessExample {json} Java示例 public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .addHeader("Cookie","tbkt_token="+tbkt_token) .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); } } // webview CookieManage cookiemanager = CookieManager.getInstance(); cookiemanager.setAcceptCookie(true); cookiemanager.setCookie(url,"sessionid="+sessionid); @apiSuccessExample {json} C#示例 HttpClient client = CreateClientASMtoken(""); HttpResponseMessage response = client.GetAsync("http://localhost").Result; IEnumerable<string> rawCookies = response.Headers.GetValues("Set-Cookie"); """ # return ajax.jsonp_fail(request, message=u'系统升级,暂停服务 20点至次日18点', error=u'升级') args = request.QUERY.casts(username=str, password=str, login_type=int, version=str, name=unicode, model=unicode, platform=str, uuid=str, appversion=str, pass_flag=int) username = args.username or '' password = args.password or '' pass_flag = int(args.pass_flag or 0) username = username.strip().lower() if not username: return ajax.jsonp_fail(request, message='请输入用户名或手机号') if not password: return ajax.jsonp_fail(request, message='请输入密码') login_type = args.login_type if pass_flag: password = auth.safe_pass_decode(password) # 模糊匹配(根据手机号+密码猜测具体帐号) if username.isdigit(): type = 3 if role == 't' else 1 encoded_password = auth.encode_plain_password(password) sql = """ select u.username, u.status from auth_user u inner join auth_profile p on p.user_id=u.id and p.password='******' where u.phone='%s' and u.type=%s """ % (encoded_password, username, type) binds = db.user_slave.fetchall_dict(sql) if not binds: return ajax.jsonp_fail(request, message='账号或密码错误,是否找回密码?') now_binds = [b for b in binds if int(b.status) != 2] if not now_binds: return ajax.jsonp_fail(request, message="该账号已被禁用,请联系客服") bind = now_binds[0] if bind: username = bind.username elif role == 't': username += 'js' else: username += 'xs' elif role == 't' and not RE_TEACHER_USERNAME.match(username): return ajax.jsonp_fail(request, message='请输入正确的教师帐号') elif role == 's' and not RE_STUDENT_USERNAME.match(username): return ajax.jsonp_fail(request, message='请输入正确的学生帐号') user, auth_user = com_user.authenticate(username=username, password=password) if not user: return ajax.jsonp_fail(request, message='账号或密码错误,是否找回密码?') if int(user.status) == 2: return ajax.jsonp_fail(request, message='该账号已被禁用,请联系客服') # 登录检查 if login_type > 1: error = com_user.app_login_check(user) if error: # 如果当前角色不让进, 通知他切换到别的角色 n = db.user_slave.auth_user.filter(phone=user.phone_number, type=user.type).count() if n > 1: auth.login(request, user.id) return ajax.jsonp_fail(request, 'switch', message=error) return ajax.jsonp_fail(request, message=error) else: error = com_user.web_login_check(user) if error: return ajax.jsonp_fail(request, message=error) # 登录日志 thread_pool.call(common.login_handle, request, args, user) data = { 'flag': "0", 'user_id': user.id } auth.login(request, user.id) if user.type==1: result=common.real_name_filter(user.real_name) if not result: data = { 'flag': "1", 'user_id': user.id } return ajax.jsonp_ok(request,data) return ajax.jsonp_ok(request, data)
def register(platform_id, user_type, phone, real_name, subject_id, dept_type): """ 注册一个帐号, 生成随机密码, 名字留空 ---------------------- 王晨光 2017-2-21 ---------------------- @param platform_id 平台ID @param user_type 用户类型 1学生 3老师 @param phone 手机号 @param real_name 姓名 @param subject_id 老师学科ID @param dept_type 学段: 1小学 2初中 @return {'user_id':用户ID, 'username':用户名, 'password':新密码} 返回None表示帐号已存在 """ def foo(user): profile = com_user.get_profile(user.id) assert profile, 'user_id: %s' % user.id password = auth.decode_plain_password(profile.password) return {'user_id': user.id, 'username': user.username, 'password': password} # 不允许同名用户注册 user = db.user.auth_user.select('id', 'username').get(phone=phone, real_name=real_name, type=user_type) if user: return foo(user) username = alloc_username(phone, user_type) user = db.user.auth_user.select('id', 'username').get(username=username) if user: return foo(user) nowt = int(time.time()) # 沿用已有帐号的密码 sql = """ select p.password from auth_user u inner join auth_profile p on p.user_id=u.id where u.type=%s and u.phone='%s' limit 1 """ % (user_type, phone) profile = db.user_slave.fetchone_dict(sql) if profile: password = auth.decode_plain_password(profile.password) else: password = "".join(random.sample('1234567890', 8)) # 新帐号随机生成6位密码 # if user_type == 3: # dept_type = 0 with db.user as c: user_id = c.auth_user.create( ignore=True, username=username, password=auth.encode_password(password), type=user_type, real_name=real_name, last_login=0, date_joined=nowt, status=1, phone=phone, platform_id=platform_id, grade_id=0, sid=subject_id, dept_id=dept_type, ) # duplicate if not user_id: user = db.user.select('id', 'username').get(username=username) assert user, '%s' % username return foo(user) # create auth_profile plain_password = auth.encode_plain_password(password) c.auth_profile.create( user_id=user_id, nickname='', portrait='', sex=1, password=plain_password, ) # 如果本手机号已经是移动开通状态, 那么这个用户也插入一条开通主记录 mslist = db.ketang_slave.mobile_subject.filter(phone_number=phone, platform_id=platform_id, pay_type='cmcc').group_by('subject_id')[:] details = [] for m in mslist: if nowt >= m.open_date and (m.cancel_date <= 0 or nowt < m.cancel_date): details.append({ 'user_id': user_id, 'phone_number': phone, 'subject_id': m.subject_id, 'open_date': m.open_date, 'cancel_date': m.cancel_date, 'pay_type': m.pay_type, 'platform_id': platform_id, 'add_date': nowt, }) if details: db.ketang.mobile_subject.bulk_create(details, ignore=True) return {'user_id': user_id, 'username': username, 'password': password}