def get(self, request): # oauth认证 code = request.GET.get("code") url = "https://api.weibo.com/oauth2/access_token" cn = OAuthWB(client_id=settings.APP_KEY, client_key=settings.APP_SECRET, redirect_uri=settings.WEIBO_REDIRECT_URI) # requests认证oauth dict = cn.get_access_token(code) uid = dict.get("uid") print(type(uid)) if uid is None: return HttpResponse("认证失败") try: # 得不到报错try 一下 # 匹配一个微博用户对象 weibo_model = OAuthSINAUser.objects.get(openid=uid) print(type(weibo_model)) except: uid = generate_openid_signature(uid) return render(request, 'oauth_callback.html', {"openid": uid}) user = weibo_model.user login(request, user) response = redirect(request.GET.get('state', '/')) response.set_cookie('username', user.username, 60 * 60 * 24 * 14) merge_cart_cookie_to_redis(request, response) return response
def post(self, request): # 获取表单账号,密码 username = request.POST.get('username') password = request.POST.get('password') remembered = request.POST.get('remembered') # 校验 # 根据表单提交用户名获取数据库中本条user信息,基本逻辑代码 # user = User.objects.get(username= username) # user.check_password(password) # 实现手机号或其他多账号登录 # 通过自定义用户认证后端实现 # django中auth自带认证方法 user = authenticate(username=username, password=password) if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 根据是否勾选记住密码保持状态 login(request, user) if remembered != 'on': request.session.set_expiry(0) else: request.session.set_expiry(None) # 在首页显示用户名 response = redirect(request.GET.get('next', '/')) # 创建好响应对象 response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE if remembered == 'on' else None) # 登录成功那一刻合并购物车 merge_cart_cookie_to_redis(request, user, response) # 响应结果重定向到首页 return response
def post(self, request, *args, **kwargs): """ 1.提取前端传来的参数 2.获取序列化器对象,传入需要反序列化的参数 3.开启校验 4.保存校验结果,返回的是保存好的user对象 5.生成jwt令牌 6.构造响应对象并返回 """ serializer = QQAuthUserSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.save() # 5.生成jwt令牌 jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) response = Response({ 'token': token, 'username': user.username, 'user_id': user.id }) # 做cookie购物车合并到redis操作 merge_cart_cookie_to_redis(request, user, response) return response
def post(self, request): '''openid绑定用户接口''' # 1.创建序列化器进行反序列化 serializer = QQAuthUserSerializer(data=request.data) # 2.调用is_valid()进行校验 serializer.is_valid(raise_exception=True) # 3.调用序列化器的save方法 user = serializer.save( ) # 因为序列化器传入data,说明调用了create()方法,create()方法返回的是个user对象 # 4.生成JWT状态保存 token jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # 引用jwt中的叫jwt_payload_handler函数(生成payload) jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # 函数引用,生成jwt payload = jwt_payload_handler(user) # 根据user生成用户相关的载荷 token = jwt_encode_handler(payload) # 传入载荷生成完整的jwt # 响应对象 response = Response({ 'token': token, 'username': user.username, 'user_id': user.user_id }) # 调用合并购物车函数 # response是个对象,对象是一个可变类型,对它进行改变,它原本就发生了变化,不需要再进行返回 merge_cart_cookie_to_redis(request, user, response) # 5.响应 return response
def post(self, request): """openid绑定用户""" # 1. 接收表单中的数据 query_dict = request.POST # dict1 = query_dict.dict() # dict1.values() mobile = query_dict.get('mobile') password = query_dict.get('password') sms_code = query_dict.get('sms_code') openid = query_dict.get('openid') # 2. 校验 if all([mobile, password, sms_code, openid]) is False: return http.HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('手机号格式有误') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20个字符的密码') # 校验短信验证码 redis_conn = get_redis_connection('verify_codes') sms_code_server = redis_conn.get('sms_%s' % mobile) redis_conn.delete('sms_%s' % mobile) if sms_code_server is None: return http.HttpResponseForbidden('短信验证码已过期') if sms_code != sms_code_server.decode(): return http.HttpResponseForbidden('短信验证码填写错误') try: # 3. 查询手机号是否已注册过 user = User.objects.get(mobile=mobile) # 4. 注册过再校验传入的密码是否正确 if user.check_password(password) is False: return http.HttpResponseForbidden('绑定失败') except User.DoesNotExist: # 5. 如果手机号是新的,就创建一个新用户 user = User.objects.create_user(username=mobile, password=password, mobile=mobile) # 对openid进行解密 openid = check_open_id(openid) if openid is None: return http.HttpResponseForbidden('openid无效') # 可以自己制作一个页面专门处理该事件 # 6.openid绑定美多新老用户 OAuthQQUser.objects.create( openid=openid, user=user, ) # 7. 状态保持 login(request, user) # 8. 存储cookie中的username response = redirect(request.GET.get('state') or '/') response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) # 合并购物车 merge_cart_cookie_to_redis(request, response) # 9. 重定向到来源 return response
def post(self, request): """账号密码登录实现逻辑""" # 接收用户名 username = request.POST.get('username') password = request.POST.get('password') remembered = request.POST.get('remembered') if all([username, password]) is False: return http.HttpResponseForbidden('缺少必传参数') # 校验 # user = User.objects.get(username=username) # user.check_password(password) # 登录认证 user = authenticate(username=username, password=password) if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) #设置状态保持的周期 if remembered != 'on': # 没有勾选记住登录 request.session.set_expiry(0) # 状态保持! login(request, user) response = redirect(request.GET.get('next') or '/' )#创建响应对象 response.set_cookie('username',user.username,max_age=60*60) # 登陆成功那一刻合并购物车 merge_cart_cookie_to_redis(request, user, response) # 响应结果重定向到首页 return response
def post(self, request): # 接受请求数据 query_dic = request.POST username = query_dic.get('username') password = query_dic.get('password') remembered = query_dic.get('remembered') # 校验 if all([username, password]) is False: return http.HttpResponseForbidden('缺少必传参数') # 用户登录验证 user = authenticate(request, username=username, password=password) if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 状态保持 login(request, user) if remembered != 'on': request.session.set_expiry(0) # 获取登录来源 next = request.GET.get('next') # 重定向到首页 response = redirect(next or '/') response.set_cookie('username', user.username, max_age=3600 * 24 * 14) merge_cart_cookie_to_redis(request, response) return response
def post(self, request): """登录功能逻辑""" # 1.接收请求体表单数据 query_dict = request.POST username = query_dict.get('username') password = query_dict.get('password') remembered = query_dict.get('remembered') # 2.校验 user = authenticate(request, username=username, password=password) # 如果登录失败 if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 3.状态保持 login(request, user) # 如果用户没有勾选记住登录 # 如果session过期时间设置为None,表示使用默认的14天,如果设置为0,代表关闭浏览器失效 # 如果cookie过期时间设置为None,表示关闭浏览器就过期,如果设置为0,代表直接删除 if remembered is None: request.session.set_expiry(0) # 是指session的过期时间为关闭浏览器过期 # 4.重定向 next = request.GET.get( 'next') # 尝试去获取查询参数中是否有用户界面的来源,如果有来源,成功登录后跳转到来源界面 response = redirect(next or '/') # 创建响应对象 # 给cookie设置username response.set_cookie('username', user.username, max_age=None if remembered is None else settings.SESSION_COOKIE_AGE) # 合并购物车 merge_cart_cookie_to_redis(request, response) return response
def post(self, request): username = request.POST.get('username') password = request.POST.get('password') remembered = request.POST.get('remembered') # 多账号登录简化版 # if re.match(r'^1[3-9]\d{9}$', username): # User.USERNAME_FIELD = 'mobile' user = authenticate(request, username=username, password=password) # User.USERNAME_FIELD = 'username' if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) login(request, user) if remembered != 'on': request.session.set_expiry(0) next = request.GET.get('next') response = redirect(next or '/') response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE if remembered else None) # 在此就做合并购物车 merge_cart_cookie_to_redis(request, response) return response
def post(self, request): # 1. 创建序列化器,表单形式--requesnt.data s = QQUserSerializer(data=request.data) # 2. 校验请求参数是否合法: serializer.is_valid() s.is_valid(raise_exception=True) # 3. 绑定openid与美多用户: serializer.save() -> serializer.create() #创建绑定的梅朵用户对象并且返回 user = s.save() # 返回绑定的美多用户对象 # 4. 生成并响应 jwt, user_id, username,完成QQ登录 # 生成jwt from rest_framework_jwt.settings import api_settings jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # 生payload部分的方法(函数) jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # 生成jwt的方法(函数) payload = jwt_payload_handler(user) # 生成payload, 得到字典 token = jwt_encode_handler(payload) # 生成jwt字符串 # 响应数据 context = { 'token': token, 'user_id': user.id, 'username': user.username } response = Response(context) # 合并购物车商品 merge_cart_cookie_to_redis(request, response, user) return Response(context)
def post(self, request): # 1.接收表单数据mobile,password,sms_code,openid query_dict = request.POST mobile = query_dict.get('mobile') password = query_dict.get('password') sms_code = query_dict.get('sms_code') openid = query_dict.get('openid') # 2.校验 if all([mobile, password, sms_code, openid]) is False: return http.HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('请输入正确的手机号') if not re.match('^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') # 对openid进行解密,将原始openid存储到表中 openid = generate_origin_openid(openid) if openid is None: return http.HttpResponseForbidden('openid无效') # 获取redis中的短信验证码 redis_conn = get_redis_connection('verify_codes') sms_code_server_bytes = redis_conn.get('sms_code_%s' % mobile) # 让短信验证码成为一次性的 redis_conn.delete('sms_code_%s' % mobile) # 判断短信验证码是否过期 if sms_code_server_bytes is None: return http.HttpResponseForbidden('短信验证码已过期') # 转换reids中短信验证码类型 sms_code_server = sms_code_server_bytes.decode() # 判断用户验证码是否正确 if sms_code != sms_code_server: return http.HttpResponseForbidden('验证码输入有误') # 以mobile字典查询user表,如果查询到就认为ie是老用户,直接用openid和老用户绑定 try: user = User.objects.get(mobile=mobile) if user.check_password(password) is False: return http.HttpResponseForbidden('老用户密码错误') except User.DoesNotExist: # 如果是美多新用户,就创建一个新用户和openid绑定 user = User.objects.create_user(username=mobile, password=password, mobile=mobile) # 3.openid绑定user OAuthQQUser.objects.create(openid=openid, user=user) # 状态保持 login(request, user) response = redirect(request.GET.get('state')) # 向cookie中存储username response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) # 合并购物车数据 merge_cart_cookie_to_redis(request,response) return response
def post(self, request): # 接收请体的表单数据 POST query_dict = request.POST mobile = query_dict.get('mobile') password = query_dict.get('password') sms_code_client = query_dict.get('sms_code') openid = query_dict.get('openid') # 校验 if all([mobile, password, sms_code_client, openid]) is False: return http.HttpResponseForbidden('缺少必须参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('请输入正确的手机号码') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') # 短信验证码校验后期补充 # 创建redis连接对象 redis_conn = get_redis_connection('verify_code') # 获取短信验证码 sms_code_server = redis_conn.get('sms_code_%s' % mobile) # 让短信验证码只能用一次 redis_conn.delete('sms_code_%s' % mobile) # 判断是否过期 if sms_code_server is None: return http.HttpResponseForbidden('短信验证码过期') # 判断用户短信验证码是否输入正确 if sms_code_client != sms_code_server.decode(): return http.HttpResponseForbidden('短信验证码输入错误') try: # 利用手机号查询user表,如果查询到用户,说明是老用户 user = User.objects.get(mobile=mobile) # 如果是老用户,再校验一个密码是否能对上 if user.check_password(password) is False: return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'}) except User.DoesNotExist: # 如果使用手机号查询不到user,说明是新用户 # 新用户就create_user 方法创建用户 user = User.objects.create_user(username=mobile, password=password, mobile=mobile) # 对openid进行解密 openid = check_openid_signature(openid) if openid is None: return http.HttpResponseForbidden('openid无效') # 新老用户绑定openid OAuthQQUser.objects.create( user=user, # user_id=user.id, openid=openid, ) # 登录成功后要做的事情 login(request, user) response = redirect(request.GET.get('state') or '/') response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) # 合并 merge_cart_cookie_to_redis(request, response) return response
def post(self, request): """ 实现登录逻辑 :param request: :return: 登录结果 """ username = request.POST.get('username') password = request.POST.get('password') remembered = request.POST.get('remembered') # django自带认证登录用户 user = authenticate(request, username=username, password=password) if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 实现状态保持 login(request, user) # 设置状态保持时长 if remembered is None: # 如果没有勾选记住登录,session会话在浏览器关闭就结束 # 默认为两周,设置为None表示默认 request.session.set_expiry(0) next = request.GET.get('next', '/') response = redirect(next) # 登录成功重定向到next页或首页 # 登录成功合并购物车数据 merge_cart_cookie_to_redis(request, response) # 用户名写入到cookie,有效期两周(前端获取到用于展示用户信息) # None表示在浏览器关闭就清除,0表示刚生成就清除了 response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE if remembered else None) return response
def post(self, request): # 接收前端传入的表单数据 query_dict = request.POST username = query_dict.get('username') password = query_dict.get('pwd') remembered = query_dict.get('remembered') # 校验 # authenticate 用户认证 user = authenticate(request, username=username, password=password) # 判断用户是否通过认证 if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 状态保持 login(request, user) # # 如果用户没有记住登录 if remembered != 'on': request.session.set_expiry(0) # 把session的过期时间设置为0 表示会话结束后就过期 # /login/?next=/info/ # /login/ # 用户如果有来源就重定向到来源,反之就去首页 response = redirect(request.GET.get('next') or '/') # 创建重定向响应对象 SESSION_COOKIE_AGE # response.set_cookie('username', user.username, max_age=(60 * 60 * 24 * 7 * 2) if remembered else None) response.set_cookie( 'username', user.username, max_age=settings.SESSION_COOKIE_AGE if remembered else None) # print(settings.SESSION_COOKIE_AGE) # 重定向到指定页 # return http.HttpResponse('登录成功,来到首页') merge_cart_cookie_to_redis(request, response) return response
def get(self, request): code = request.GET.get('code') if code is None: return http.HttpResponseForbidden('缺少code') client = APIClient(app_key=settings.SINA_CLIENT_ID, app_secret=settings.SINA_CLIENT_SECRET, redirect_uri=settings.SINA_REDIRECT_URI) try: token_dict = client.request_access_token(code) access_token = token_dict.access_token except Exception as e: logger.error(e) return http.HttpResponseForbidden('code无效') try: sina_u = OAuthSinaUser.objects.get(uid=access_token) except OAuthSinaUser.DoesNotExist: return http.JsonResponse({'access_token': access_token}) else: user = sina_u.user data = { 'user_id': user.id, 'username': user.username, 'token': access_token } login(request, user) response = http.JsonResponse(data) response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) merge_cart_cookie_to_redis(request, response) return response
def post(self, request): """openid绑定到用户""" # 创建序列化器对象,进行反序列化 serializer = QQAuthUserSerializer(data=request.data) # 开启校验 serializer.is_valid(raise_exception=True) # 保存校验结果,并接收 user = serializer.save() # 手动生成jwt Token jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # 加载生成载荷函数 jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # 加载生成token函数 # 获取user对象 payload = jwt_payload_handler(user) # 生成载荷 token = jwt_encode_handler(payload) # 根据载荷生成token response = Response({ 'token': token, 'username': user.username, 'user_id': user.id }) # 做cookie购物车合并到redis操作 merge_cart_cookie_to_redis(request, user, response) return response
def post(self,request): mobile = request.POST.get('mobile') pwd = request.POST.get('password') sms_code_client = request.POST.get('sms_code') openid = request.POST.get('openid') if not all([mobile,pwd,sms_code_client,openid]): return HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}',mobile): return HttpResponseForbidden('电话号码错误') redis_conn=get_redis_connection('verify_code') ver_code=redis_conn.get('sms_%s' % mobile) # if ver_code is None: # return JsonResponse({'code': RETCODE.SMSCODERR, 'errmsg': '短信验证码已过期'}) # if ver_code.decode()!=sms_code_client: # return JsonResponse({'code': RETCODE.SMSCODERR, 'errmsg': '短信验证码错误'}) if not re.match(r'^[0-9A-Za-z]{8,20}$', pwd): return HttpResponseForbidden('请输入8-20位的密码') openid=check_openid_signature(openid) if not openid: return HttpResponseForbidden('绑定失败') try: user=User.objects.get(mobile=mobile) if not user.check_password(pwd): return JsonResponse({'code': RETCODE.PWDERR, 'errmsg': '密码错误'}) except User.DoesNotExist: user=User.objects.create_user(username=mobile,password=pwd,mobile=mobile) OAuthQQUser.objects.create(user=user, openid=openid) login(request, user) response = redirect(request.GET.get('state') or '/') response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) merge_cart_cookie_to_redis(request=request, response=response) return response
def post(self, request): """实现openid绑定用户逻辑""" # 接收数据 mobile = request.POST.get('mobile') password = request.POST.get('password') sms_code = request.POST.get('sms_code') openid = request.POST.get('openid') if all([mobile, password, sms_code, openid]) is False: return http.HttpResponseForbidden('缺少必传参数') # 校验 if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('您输入的手机号格式不正确') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') # 短信验证码校验后期再补充 redis_coon = get_redis_connection('verify_code') sms_code_server = redis_coon.get('sms_%s' % mobile) # 获取redis中的短信验证码 if sms_code_server is None or sms_code != sms_code_server.decode(): return http.HttpResponseForbidden('短信验证码有误') # 校验openid openid = check_openid_sign(openid) if openid is None: return http.HttpResponseForbidden('openid无效') # 绑定用户 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: # 当前要绑定的用户是一个新用户 user = User.objects.create_user( username=mobile, password=password, mobile=mobile, ) else: # 当前要绑定的用户是已存在 if user.check_password(password) is False: return http.HttpResponseForbidden('账号或密码错误') # 如果代码能执行到这里,用户user绝对已经有了 # 用户openid和user绑定 OAuthQQUser.objects.create(user=user, openid=openid) # 重定向 login(request, user) response = redirect(request.GET.get('state')) response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) # 登陆成功那一刻合并购物车 merge_cart_cookie_to_redis(request, user, response) return response
def post(self, request): """ 实现登录逻辑 :param request: 请求对象 :return: 登录结果 """ # 接收参数 username = request.POST.get('username') password = request.POST.get('password') remembered = request.POST.get('remembered') # 认证登录用户 user = authenticate(username=username, password=password) if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 实现登录状态保持 login(request, user) # 设置状态保持的周期 if remembered != 'on': # 没有记住用户: 浏览器会话结束就过期,默认是两周 request.session.set_expiry(0) next = request.GET.get('next') # if next: # # response = redirect(next) # # # else: # # 响应登录结果 # # # return redirect(reverse('contents:index')) 实现首页显示登录名,此处要将用户名等信息写出cookie # # response = redirect(reverse('contents:index')) response = redirect(next or "/") # 登录时用户名写入cookie,有效期14天 response.set_cookie('username', user.username, max_age=(None if remembered is None else settings.SESSION_COOKIE_AGE)) merge_cart_cookie_to_redis(request, response) return response
def post(self, request, *args, **kwargs): response = super().post(request, *args, **kwargs) # 合并购物车 user = self.user merge_cart_cookie_to_redis(request, user, response) return response
def get(self, request): # 1.获取前端传入的code code = request.query_params.get('code') if not code: return Response({'message': '缺少code'}, status=status.HTTP_400_BAD_REQUEST) # 2.创建QQ登录工具对象 oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI) # 不需要next参数 try: # 3.调用它里面get_access_token(code) 用code响应QQ服务器获取access_token access_token = oauth.get_access_token(code) # 4.调用它里面get_open_id(access_token) 用access_token响应QQ服务器获取openid openid = oauth.get_open_id(access_token) except Exception as e: # 捕获其他异常 logging.info(e) # 输出到终端和日志文件中 return Response({'message': 'QQ服务器不可用'}, status=status.HTTP_503_SERVICE_UNAVAILABLE) # 5.查询数据库有没有这个openid try: authQQUserModel = OAuthQQUser.objects.get(openid=openid) except OAuthQQUser.DoesNotExist: # 6.如果没有这个openid,没有绑定用户,把openid加密之后响应给前端,让前端先暂存一会,等待绑定时使用 # access_token是由于前端写错了,本应该是openid # 没有绑定openid,无法识别用户,不能使用服务器资源,所以只能将openid传给前端,让前端保存 # 因为openid是QQ用户的唯一身份标志,直接传前端可见,需要进行加密传输 access_token_openid = generate_save_user_token(openid) return Response({'access_token': access_token_openid}) else: # 7.如果有这个openid,直接代码登录成功,给前端返回JWT状态保存信息 # 获取到openid 关联的user user = authQQUserModel.user # 通过外键获取user模型对象 jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # 引用jwt中的叫jwt_payload_handler函数(生成payload) jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # 函数引用,生成jwt payload = jwt_payload_handler(user) # 根据user生成用户相关的载荷 token = jwt_encode_handler(payload) # 传入载荷生成完整的jwt # 响应对象 response = Response({ 'token': token, 'username': user.username, 'user_id': user.user_id }) # 调用合并购物车函数 # response是个对象,对象是一个可变类型,对它进行改变,它原本就发生了变化,不需要再进行返回 merge_cart_cookie_to_redis(request, user, response) return response
def post(self, request): """绑定用户处理""" # 1.接受数据 query_dict = request.POST mobile = query_dict.get('mobile') password = query_dict.get('password') sms_code = query_dict.get('sms_code') openid = query_dict.get('openid') # 2.校验 if all([mobile, password, sms_code, openid]) is False: return http.HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('您输入的手机号格式不正确') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') # 连接redis数据库获取短信标识 redis_conn = get_redis_connection('verify_code') sms_code_server = redis_conn.get('sms_code_%s' % mobile) if sms_code_server is None: return render(request, 'oauth_callback.html', {'sms_code_errmsg': '短信验证码已失效'}) if sms_code_server.decode() != sms_code: return render(request, 'oauth_callback.html', {'sms_code_errmsg': '请输入正确的验证码'}) # 对openid进行解密 openid = check_openid_signature(openid) if openid is None: return http.HttpResponseForbidden('openid无效') # 3.处理逻辑 # 先判断用户是否存在,如果用户的手机号在user表中查不到创建一个新的用户 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: # 表示没有该用户,需要创建一个新的用户 user = User.objects.create_user(mobile=mobile, password=password, username=mobile) else: # 用户存在,判断该用户的密码是否正确 if user.check_password(password) is False: return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或者密码错误'}) # openid和用户绑定 OAuthQQUser.objects.create(openid=openid, user=user) login(request, user) # 保持状态 next = request.GET.get('state') # 获取用户界面来源 response = redirect(next or '/') # 创建响应对象及重定向 # 向cookie中设置username以备在状态栏显示用户的用户名 response.set_cookie('username', user.username, max_age=300) # 在此处就作合并购物车 merge_cart_cookie_to_redis(request, response) # 4.响应 return response
def post(self, request): # 根据用户传递来的手机号,判断用户是否注册美多商城账号 user_info = json.loads(request.body.decode()) mobile = user_info.get('mobile') password = user_info.get('password') sms_code = user_info.get('sms_code') access_token = user_info.get("access_token") if not all([mobile, password, sms_code, access_token]): return JsonResponse({'code': 400, 'errmsg': '缺少参数'}) # 判断手机号是否合法 if not re.match(r'^1[3-9]\d{9}$', mobile): return JsonResponse({'code': 400, 'errmsg': '请输入正确的手机号码'}) # 判断密码是否合格 if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return JsonResponse({'code': 400, 'errmsg': '请输入8-20位的密码'}) conn = get_redis_connection('sms_code') sms_code_fron_redis = conn.get('sms_%s' % mobile) if not sms_code_fron_redis: return JsonResponse({'code': 400, 'errmsg': '验证码过期'}) if sms_code_fron_redis.decode() != sms_code: return JsonResponse({'code': 400, 'errmsg': '您输入的短信验证码有误!'}) # 把openid从access_token参数中解密出来 openid = check_access_token(access_token) # =============================================== # 不绑定的两种情况 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist as e: print(e) # 1、没有注册,新建再绑定 user = User.objects.create_user(username=mobile, mobile=mobile, password=password) # 绑定openid OAuthQQUser.objects.create(openid=openid, user=user) login(request, user) response = JsonResponse({'code': 0, 'errmsg': 'ok'}) response.set_cookie('username', user.username, max_age=3600 * 24 * 14) response = merge_cart_cookie_to_redis(request, user, response) return response # 2、已经注册,直接绑定 # 绑定openid OAuthQQUser.objects.create(openid=openid, user=user) login(request, user) response = JsonResponse({'code': 0, 'errmsg': 'ok'}) response.set_cookie('username', user.username, max_age=3600 * 24 * 14) response = merge_cart_cookie_to_redis(request, user, response) return response
def post(self, request, *args, **kwargs): response = super(UserAuthorizeView, self).post(request, *args, **kwargs) serializer = self.get_serializer(data=request.data) if serializer.is_valid(): user = serializer.object.get('user') or request.user merge_cart_cookie_to_redis(request, response, user) return response
def get(self, request): """Oauth2.0认证""" # 接收Authorization Code code = request.GET.get('code') if not code: return HttpResponseForbidden("缺少code") # 创建工具对象 oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI) try: # 使用code向QQ服务器请求access_token access_token = oauth.get_access_token(code) # 使用access_token向QQ服务器请求openid openid = oauth.get_open_id(access_token) except Exception as e: logger.error(e) return HttpResponseServerError("OAuth2.0认证失败") try: oauth_user = OAuthQQUser.objects.get(openid=openid) except OAuthQQUser.DoesNotExist: # 如果openid没绑过美多商城用户 openid = generate_openid_signature(openid) context = {'openid': openid} return render(request, 'oauth_callback.html', context) else: # 如果已经绑定过美多商城用户 qq_user = oauth_user.user login(request, qq_user) # 响应结果 # 获取界面跳转来源 response = redirect(request.GET.get('state') or "/") # 登录时用户名写入到cookie,有效期15天 response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 14) merge_cart_cookie_to_redis(request, response) return response
def post(self, request): # 1、提取参数 data = json.loads(request.body.decode()) mobile = data.get('mobile') password = data.get('password') sms_code = data.get('sms_code') access_token = data.get('access_token') # 加密的{"openid": "123456789"} # 2、校验参数 # 2.1、必要性校验 if not all([mobile, password, sms_code, access_token]): return JsonResponse({'code': 400, 'errmsg': '缺少必要参数'}) # 2.2、约束性校验 if not re.match(r'^1[3-9]\d{9}$', mobile): return JsonResponse({'code': 400, 'errmsg': '手机号格式有误'}) if not re.match(r'^[a-zA-Z0-9]{8,20}$', password): return JsonResponse({'code': 400, 'errmsg': '密码格式有误'}) # 2.3、业务性校验 conn = get_redis_connection('verify_code') sms_code_from_redis = conn.get('sms_%s' % mobile) if not sms_code_from_redis: return JsonResponse({'code': 400, 'errmsg': '短信验证码过期'}) if sms_code != sms_code_from_redis.decode(): return JsonResponse({'code': 400, 'errmsg': '短信验证码输入错误'}) # 3、业务数据处理 —— 绑定账号 # 3.1、解密openid data_dict = SecretOauth().loads( access_token) # {"openid": "1234567890"} or None if not data_dict: return JsonResponse({'code': 400, 'errmsg': 'openid有误!'}) openid = data_dict.get('openid') # 3.2、根据用户传递的手机号查找用户对象 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist as e: # 未注册美多账号 —— 新建绑定 user = User.objects.create_user(username=mobile, mobile=mobile, password=password) else: # 注册过美多账号 —— 直接绑定 if not user.check_password(password): return JsonResponse({'code': 400, 'errmsg': '密码错误'}) # 绑定 OAuthQQUser.objects.create(user=user, openid=openid) # 4、构建响应 login(request, user) response = JsonResponse({'code': 0, 'errmsg': 'ok'}) response.set_cookie('username', user.username, max_age=3600 * 24 * 14) # TODO: 合并购物车 merge_cart_cookie_to_redis(request, response) return response
def post(self, request): # 获取表单数据 query_dict = request.POST username = query_dict.get('username') password = query_dict.get('pwd') remembered = query_dict.get('remembered') # 校验数据 if all([username, password]) is None: return HttpResponseForbidden("缺少必要的参数") if not re.match('^[a-zA-Z0-9_-]{5,20}$', username): return render(request, 'login.html', {'loginerror': '帐号或密码错误'}) if not re.match('^[0-9A-Za-z]{8,20}$', password): return render(request, 'login.html', {'loginerror': '帐号或密码错误'}) # 多帐号登录功能实现 # try: # user = User.objects.get(username=username) # except User.DoesNotExist: # try: # user = User.objects.get(mobile=username) # except User.DoesNotExist: # return render(request, 'login.html', {'account_errmsg': '帐号或密码错误'}) # # if user.check_password(password) is False: # return render(request, 'login.html', {'account_errmsg': '帐号或密码错误'}) # 用户认证 authenticate(请求对象, 认证参数), 查询不到用户返回None user = authenticate(request, username=username, password=password) if user is None: return render(request, 'login.html', {'loginerror': '帐号或密码错误'}) # 状态保持 login(request, user) if remembered is None: request.session.set_expiry(0) else: request.session.set_expiry(settings.SESSION_COOKIE_AGE) # response = redirect('/') # 根据查询参数next的值重定向 response = redirect(request.GET.get('next') or '/') merge_cart_cookie_to_redis(request, response) # 设置cookie response.set_cookie( 'username', user.username, max_age=settings.SESSION_COOKIE_AGE if remembered else None) return response
def get(self, request): """提取code请求参数""" code = request.query_params.get('code') if not code: return Response({'message': '缺少code的值'}, status=status.HTTP_400_BAD_REQUEST) # 1.1 创建qq登录工具对象 oauthqq = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI) try: # 2.通过code向QQ服务器请求获取access_token access_token = oauthqq.get_access_token(code) # 3.通过access_token向QQ服务器请求获取openid openid = oauthqq.get_open_id(access_token) except Exception as e: logger.info(e) return Response({'message': 'QQ服务器异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE) # 4.查询openid是否绑定过美多商城中的用户 try: qqauth_model = QQAuthUser.objects.get(openid=openid) except QQAuthUser.DoesNotExist: # 如果qqauth_model异常,说明用户没有进行过QQ登录, # 如果openid没有绑定过美多商城中的用户 # 把openid进行加密安全处理,再响应给浏览器,让它先帮我们保存一会 openid_save = generate_save_user_token(openid) return Response({'access_token': openid_save}) else: # 如果openid已经绑定过美多商城中的用户(生成jwt token直接让它登录成功) # 手动生成token # QQ登录的状态保持 jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # 加载生成载荷函数 jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # 加载生成token函数 user = qqauth_model.user # 通过第三方QQ的数据的用户获取user(user是外键,可以得到User) payload = jwt_payload_handler(user) # 生成载荷 token = jwt_encode_handler(payload) # 根据载荷生成token # 返回值 response = Response({ 'token': token, 'username': user.username, 'user_id': user.id, }) # 做cookie购物车合并到redis操作 merge_cart_cookie_to_redis(request, user, response) return response
def post(self, request): """用户注册功能""" # 接收前端传入的表单数据: username, password, password2, mobile, sms_code, allow username = request.POST.get('username') password = request.POST.get('password') password2 = request.POST.get('password2') mobile = request.POST.get('mobile') sms_code = request.POST.get('sms_code') allow = request.POST.get('allow') # 单选框如果勾选就是 'on',如果没有勾选 None # all None, False, '' # 校验前端传入的参数是否齐全 if all([username, password, password2, mobile, sms_code, allow]) is False: return http.HttpResponseForbidden('缺少必传参数') # 校验数据前端传入数据是否符合要求 if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username): return http.HttpResponseForbidden('请输入5-20个字符的用户名') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') if password != password2: return http.HttpResponseForbidden('输入的密码两次不一致') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('您输入的手机号格式不正确') # 短信验证码校验后期再补充 redis_coon = get_redis_connection('verify_code') sms_code_server = redis_coon.get('sms_%s' % mobile) # 获取redis中的短信验证码 if sms_code_server is None or sms_code != sms_code_server.decode(): return http.HttpResponseForbidden('短信验证码有误') # 创建一个user try: user = User.objects.create_user( username=username, password=password, # 密码在存储时需要加密后再存到表中 mobile=mobile ) except DatabaseError as e: logger.error(e) return render(request, 'register.html', {'register_errmsg': '用户注册失败'}) # 状态保持 login(request, user) # 存储用户的id到session中记录它的登录状态 response = redirect('/') # 创建好响应对象 response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) merge_cart_cookie_to_redis(request, response) # 响应结果重定向到首页 return response
def post(self, request): # 1.接收表单数据 query_dict = request.POST mobile = query_dict.get('mobile') password = query_dict.get('password') sms_code = query_dict.get('sms_code') openid = query_dict.get('openid') # 校验 if all([mobile, password, sms_code, openid]) is False: return http.HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('请输入5-20个字符的用户名') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') redis_conn = get_redis_connection('verify_code') sms_code_server = redis_conn.get('sms_%s' % mobile) redis_conn.delete('sms_%s' % mobile) if sms_code_server is None: return http.HttpResponseForbidden('短信验证码过期') sms_code_server = sms_code_server.decode() if sms_code != sms_code_server: return http.HttpResponseForbidden('请输入正确的短信验证码') openid = check_openid_signature(openid) if openid is None: return http.HttpResponseForbidden('openid无效') try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: user = User.objects.create_user(mobile=mobile, password=password, username=mobile) else: if user.check_password(password) is False: return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'}) # openid和用户绑定 OAuthQQuser.objects.create(openid=openid, user=user) login(request, user) next = request.GET.get('state') response = redirect(next or '/') response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE) # 在此就做合并购物车 merge_cart_cookie_to_redis(request, response) return response
def post(self, request): """ 实现登录逻辑 :param request:请求对象 :return: 登录结果 """ # 1.接收参数 username = request.POST.get('username') password = request.POST.get('password') remembered = request.POST.get('remembered') # 2.校验参数 # 判断参数是否齐全 # 这里注意:remembered 这个参数可以是 None 或者是 ‘no’ # 所以我们不对它是否存在进行判断 if not all([username, password]): return http.HttpResponseForbidden('缺少必传参数') # 判断用户名是否是5-20个字符 if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username): return http.HttpResponseForbidden('请输入正确的用户名或手机号') # 判断密码是否是8-20个数字 if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('密码最少8位,最长20位') # 认证登录用户 authenticate 是django自带的认证用户方法,返回用户名 user = authenticate(username=username, password=password) if user is None: return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'}) # 实现状态保持 login(request, user) # 设置状态保持的周期 if remembered != 'on': request.session.set_expiry(0) else: request.session.set_expiry(None) # 获取跳转过来的地址 next = request.GET.get('next') # 判断参数是否存在 if next: # 如果是从别的页面跳转过来的, 则重新跳转到原来的页面 response = redirect(next) else: # 生成响应对象 # 如果不是从别的页面跳转过来的,就重定向到首页 response = redirect(reverse('contents:index')) # 在响应对象中设置用户名信息 # 将用户名写入到 cookie,有效期15天 response.set_cookie('username', user.username, max_age=3600 * 24 * 15) # 合并购物车 response = merge_cart_cookie_to_redis(request, user, response) # 返回响应结果 return response
def get(self, request): """Oauth2.0认证""" # 接收Authorization Code code = request.GET.get('code') if not code: return http.HttpResponseForbidden('缺少code') # 创建工具对象 oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI) try: # 携带 code 向 QQ服务器 请求 access_token access_token = oauth.get_access_token(code) # 携带 access_token 向 QQ服务器 请求 openid openid = oauth.get_open_id(access_token) except Exception as e: # 如果上面获取 openid 出错, 则验证失败 logger.error(e) # 返回结果 return http.HttpResponseServerError('OAuth2.0认证失败') try: oauth_user = OAuthQQUser.objects.get(openid=openid) except OAuthQQUser.DoesNotExist: # 如果 openid 没绑定美多商城用户,进入这里: # 调用我们封装好的方法, 对 openid 进行加密, 生成 access_token 字符串 access_token = generate_access_token(openid) # 拿到 access_token 字符串后, 拼接字典 context = {'access_token': access_token} # 返回响应, 重新渲染 return render(request,'oauth_callback.html', context) else: # 如果 openid 已绑定美多商城用户 # 根据 user 外键, 获取对应的 QQ用户 qq_user = oauth_user.user # 实现状态保持 login(request, qq_user) # 创建重定向到主页的对象 response = redirect(reverse('contents:index')) # 将用户信息写入到 cookie 中,有效期15天 response.set_cookie('username',qq_user.username,max_age=3600 * 24 * 15) # 合并购物车 response = merge_cart_cookie_to_redis(request=request, user=qq_user, response=response) # 返回响应 return response
def post(self, request): """美多商城用户绑定到openid""" # 1.接收参数 mobile = request.POST.get('mobile') password = request.POST.get('password') sms_code_client = request.POST.get('sms_code') access_token = request.POST.get('access_token') # 2.校验参数 # 判断参数是否齐全 if not all([mobile, password, sms_code_client]): return http.HttpResponseForbidden('缺少必传参数') # 判断手机号是否合法 if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('请输入正确的手机号码') # 判断密码是否合格 if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位密码') # 3.判断短信验证码是否一致 # 创建 redis 链接对象: redis_conn = get_redis_connection('verify_code') # 从 redis 中获取 sms_code 值: sms_code_server = redis_conn.get('sms_code_%s' % mobile) print(sms_code_server) # 判断获取出来的有没有 if sms_code_server is None: # 如果没有,直接返回: return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'}) # 如果有,则进行判断: if sms_code_client != sms_code_server.decode(): # 如果不匹配,则直接返回: return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入的短信验证码有误'}) # 调用我们自定义的函数, 检验传入的 access_token 是否正确: # 错误提示放在 sms_code_errmsg 位置 openid = check_access_token(access_token) if openid is None: return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'}) # 4.保存注册数据 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: # 用户不存在, 新建用户 user = User.objects.create_user(username=mobile, password=password, mobile=mobile) else: # 如果用户存在, 检查用户密码 if not user.check_password(password): return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'}) # 5.将用户绑定 openid try: OAuthQQUser.objects.create(openid=openid, user=user) except DatabaseError: return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'}) # 6.实现状态保持 login(request, user) # 7.响应绑定结果 next = request.GET.get('next', '/') response = redirect(next) # 8.登录是用户名写入到 cookid, 有效期 15天 response.set_cookie('username', user.username, max_age=3600 * 24 * 15) # 合并购物车 response = merge_cart_cookie_to_redis(request, user, response) # 9.返回(从哪里来到那里去) return response