您现在的位置是: 网站首页 >Django >Vue+Django REST framework前后端分离生鲜电商 Django

【Vue+DRF生鲜电商】35.使用social-app-django集成第三方登录

admin2019年10月30日 11:29 Django | Html | JavaScript | Vue 134人已围观

Vue+Django REST framework前后端分离生鲜电商简介 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ; Django版本:2.2、djangorestframework:3.9.2。 前端Vue模板可以直接联系我拿。

## social-app-django集成第三方登录 访问 https://github.com/python-social-auth/social-app-django 可以看到项目 Python Social Auth是一种易于设置的社交认证/注册机制,支持多个框架和auth提供程序。 这是python-social-auth生态系统的Django组件,它实现了在基于Django的项目中集成social-auth-core所需的功能。 官方文档: https://python-social-auth.readthedocs.io/en/latest/ Python Social Auth旨在为支持OAuth(1和2),OpenId等协议的Python项目提供易于设置的社交认证和授权机制。 初始代码库源自django-social-auth,其思想是将流程概括为适应不同的框架,提供所需的工具来为新框架提供支持。 django-social-auth本身是来自django-twitter-oauth和django-openid-auth项目的修改代码的产物。 该项目现在分为较小的模块,以隔离和减少责任并提高可重用性。 多框架支持: > - [Django](https://github.com/python-social-auth/social-app-django) > - [Flask](https://github.com/python-social-auth/social-app-flask) > - [Pyramid](http://www.pylonsproject.org/projects/pyramid/about) > - [Webpy](https://github.com/python-social-auth/social-app-webpy) > - [Tornado](http://www.tornadoweb.org/) ### Django框架下使用 Django框架下使用文档: https://python-social-auth.readthedocs.io/en/latest/configuration/django.html #### 安装social-auth-app-django ```bash pip install social-auth-app-django ``` #### 添加social_django到应用 将`social_django`添加到`INSTALLED_APPS`中 ```python INSTALLED_APPS = [ # 'simpleui', # 第三方后台,使用https://github.com/newpanjing/simpleui 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 添加drf应用 'rest_framework', 'rest_framework.authtoken', 'django_filters', # 添加Django联合登录 'social_django', # Django跨域解决 'corsheaders', # 注册富文本编辑器ckeditor 'ckeditor', # 注册富文本上传图片ckeditor_uploader 'ckeditor_uploader', 'users.apps.UsersConfig', 'goods.apps.GoodsConfig', 'trade.apps.TradeConfig', 'user_operation.apps.UserOperationConfig', ] ``` #### 生成social_django相关的表 将`social_django`添加到已安装的应用程序后,需要同步数据库以创建所需的模型: ![BLOG_20191030_113534_50](/media/blog/images/2019/10/BLOG_20191030_113534_50.png "博客图集BLOG_20191030_113534_50.png") ```bash # 直接执行migrate即可,不用执行makemigrations,因为安装应用已经存在这些文件了 > migrate Tracking file by folder pattern: migrations Operations to perform: Apply all migrations: admin, auth, authtoken, contenttypes, goods, sessions, social_django, trade, user_operation, users Running migrations: Applying social_django.0001_initial... OK Applying social_django.0002_add_related_name... OK Applying social_django.0003_alter_email_max_length... OK Applying social_django.0004_auto_20160423_0400... OK Applying social_django.0005_auto_20160727_2333... OK Applying social_django.0006_partial... OK Applying social_django.0007_code_timestamp... OK Applying social_django.0008_partial_timestamp... OK ``` 数据库就生成了以下的表 ![BLOG_20191030_113525_40](/media/blog/images/2019/10/BLOG_20191030_113525_40.png "博客图集BLOG_20191030_113525_40.png") #### 身份验证后端配置 将所需的身份验证后端添加到Django的`AUTHENTICATION_BACKENDS`设置: 官方示例: ```python AUTHENTICATION_BACKENDS = ( 'social_core.backends.open_id.OpenIdAuth', 'social_core.backends.google.GoogleOpenId', 'social_core.backends.google.GoogleOAuth2', 'social_core.backends.google.GoogleOAuth', 'social_core.backends.twitter.TwitterOAuth', 'social_core.backends.yahoo.YahooOpenId', ... 'django.contrib.auth.backends.ModelBackend', ) ``` 考虑到后端必须在`AUTHENTICATION_BACKENDS`中定义,否则Django在尝试验证用户时不会选择它们。 **如果使用`django.contrib.auth`应用程序,不要忘记添加`django.contrib.auth.backends.ModelBackend`,否则用户将无法通过用户名/密码方法登录。** 示例中,支持的认证类有`OpenIdAuth`、`GoogleOAuth2`等,想要查看其他支持的类型,可以访问安装库的位置`*PATH*/site-packages/social_core/backends`查看。 例如,要使用微博登录,找到 `weibo.py` 文件,它的源码如下: ```python # *PATH*/site-packages/social_core/backends/weibo.py # coding:utf-8 # author:hepochen@gmail.com https://github.com/hepochen """ Weibo OAuth2 backend, docs at: https://python-social-auth.readthedocs.io/en/latest/backends/weibo.html """ from .oauth import BaseOAuth2 class WeiboOAuth2(BaseOAuth2): """Weibo (of sina) OAuth authentication backend""" name = 'weibo' ID_KEY = 'uid' AUTHORIZATION_URL = 'https://api.weibo.com/oauth2/authorize' REQUEST_TOKEN_URL = 'https://api.weibo.com/oauth2/request_token' ACCESS_TOKEN_URL = 'https://api.weibo.com/oauth2/access_token' ACCESS_TOKEN_METHOD = 'POST' REDIRECT_STATE = False EXTRA_DATA = [ ('id', 'id'), ('name', 'username'), ('profile_image_url', 'profile_image_url'), ('gender', 'gender') ] def get_user_details(self, response): """Return user details from Weibo. API URL is: https://api.weibo.com/2/users/show.json/?uid=<UID>&access_token=<TOKEN> """ if self.setting('DOMAIN_AS_USERNAME'): username = response.get('domain', '') else: username = response.get('name', '') fullname, first_name, last_name = self.get_user_names( first_name=response.get('screen_name', '') ) return {'username': username, 'fullname': fullname, 'first_name': first_name, 'last_name': last_name} def get_uid(self, access_token): """Return uid by access_token""" data = self.get_json( 'https://api.weibo.com/oauth2/get_token_info', method='POST', params={'access_token': access_token} ) return data['uid'] def user_data(self, access_token, response=None, *args, **kwargs): """Return user data""" # If user id was not retrieved in the response, then get it directly # from weibo get_token_info endpoint uid = response and response.get('uid') or self.get_uid(access_token) user_data = self.get_json( 'https://api.weibo.com/2/users/show.json', params={'access_token': access_token, 'uid': uid} ) user_data['uid'] = uid return user_data ``` 在现有项目中,我们的配置为 ```python AUTHENTICATION_BACKENDS = ('users.views.CustomBackend',) # 指定认证后台 ``` 所以,要在项目中使用微博登录,只需要修改 DjangoOnlineFreshSupermarket/settings.py ,将`AUTHENTICATION_BACKENDS`添加微博认证后端,实际配置如下 ```python AUTHENTICATION_BACKENDS = ( 'users.views.CustomBackend', # 自定义认证后端 'social_core.backends.weibo.WeiboOAuth2', # 微博认证后端 'social_core.backends.qq.QQOAuth2', # QQ认证后端 'social_core.backends.weixin.WeixinOAuth2', # 微信认证后端 'django.contrib.auth.backends.ModelBackend', # 使用了`django.contrib.auth`应用程序,支持帐密认证 ) # 指定认证后台 ``` #### 添加认证URL 修改 DjangoOnlineFreshSupermarket/urls.py 的`urlpatterns`,添加以下路由 ```python urlpatterns = [ # ...省略其他path # social_django认证登录 path('', include('social_django.urls', namespace='social')) ] ``` 如果需要自定义命名空间,还需要修改 settings.py 增加以下设置: ```python SOCIAL_AUTH_URL_NAMESPACE = 'social' ``` 可以查看`social_django.urls`的源码如下: ```python """URLs module""" from django.conf import settings from django.conf.urls import url from social_core.utils import setting_name from . import views extra = getattr(settings, setting_name('TRAILING_SLASH'), True) and '/' or '' app_name = 'social' urlpatterns = [ # authentication / association url(r'^login/(?P<backend>[^/]+){0}$'.format(extra), views.auth, name='begin'), url(r'^complete/(?P<backend>[^/]+){0}$'.format(extra), views.complete, name='complete'), # disconnection url(r'^disconnect/(?P<backend>[^/]+){0}$'.format(extra), views.disconnect, name='disconnect'), url(r'^disconnect/(?P<backend>[^/]+)/(?P<association_id>\d+){0}$' .format(extra), views.disconnect, name='disconnect_individual'), ] ``` 这里面`backend`代表认证后端py文件名,比如`'social_core.backends.weibo.WeiboOAuth2'`就是`weibo`,'social_core.backends.qq.QQOAuth2'就是`qq`,其他类推。 这里面和之前手写的微博授权登陆逻辑类似。 #### 模板使用示例(DRF不用) 模板中`google-oauth2`后端使用示例: ```html <a href="{% url "social:begin" "google-oauth2" %}">Google+</a> ``` #### 模板上下文处理器 有一个上下文处理器,它将后端和关联数据添加到模板上下文: 添加`'social_django.context_processors.backends',`和`'social_django.context_processors.login_redirect',`到`context_processors`中: ```python TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', # 添加下面2条social_django上下文处理器 'social_django.context_processors.backends', 'social_django.context_processors.login_redirect', ], }, }, ] ``` #### 测试social_django登录 由于是Django2.2+版本了, DjangoOnlineFreshSupermarket/urls.py 中的`path('login/', simplejwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'), # 登录一般是login`和 PATH/site-packages/social_django/urls.py 中的 `url(r'^login/(?P<backend>[^/]+){0}$'.format(extra), views.auth, name='begin'),` ,虽然同为`/login/`,但是不会冲突的,不用担心。 可以访问 http://127.0.0.1:8000/login/weibo/ 测试 ![BLOG_20191030_113510_36](/media/blog/images/2019/10/BLOG_20191030_113510_36.png "博客图集BLOG_20191030_113510_36.png") 出现这个问题,是因为没有配置,接着往下看 ### OAuth应用Key和Secret配置 #### 微博回调URL修改 在 `social_django` 的 PATH/site-packages/social_django/urls.py 中,回调url是 ```python url(r'^complete/(?P<backend>[^/]+){0}$'.format(extra), views.complete, name='complete'), ``` 所以需要修改微博认证的授权回调页为 http://127.0.0.1:8000/complete/weibo/ 和本机的IP地址保持一致,如果是部署到服务器就是用服务器的IP: ![BLOG_20191030_113503_35](/media/blog/images/2019/10/BLOG_20191030_113503_35.png "博客图集BLOG_20191030_113503_35.png") #### 配置应用 配置文档: https://python-social-auth.readthedocs.io/en/latest/configuration/settings.html 参考官网示例 安装程序需要OAuth密钥 ```python SOCIAL_AUTH_TWITTER_KEY = 'foobar' SOCIAL_AUTH_TWITTER_SECRET = 'bazqux' ``` OpenId后端通常不需要密钥,但有些需要一些API密钥来调用提供程序上的任何API。 检查后端部分以获取详细信息。 可以写成自己的,为了不上传到网上,将在 ProjectConfig.ini 配置文件中写这些值 先修改项目根目录下的 ProjectConfig.ini ```ini [DjangoOnlineFreshSupermarket] server_ip=xx.ip.ip.xx weibo_key=224xxxx919 weibo_secret=bd43cebdxxxxxxxxc093xxxxxxxx513a ``` 然后修改 DjangoOnlineFreshSupermarket/settings.py 添加 ```python # social_django配置OAuth keys,项目上传晚上,将涉密信息保存在配置文件中 import configparser config = configparser.ConfigParser() config.read(os.path.join(BASE_DIR, 'ProjectConfig.ini')) weibo_key = config['DjangoOnlineFreshSupermarket']['weibo_key'] weibo_secret = config['DjangoOnlineFreshSupermarket']['weibo_secret'] SOCIAL_AUTH_WEIBO_KEY = weibo_key SOCIAL_AUTH_WEIBO_SECRET = weibo_secret SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/index/' # 登录成功后跳转,一般为项目首页 ``` 接下来访问 http://127.0.0.1:8000/login/weibo/ 会跳转到 https://api.weibo.com/oauth2/authorize?client_id=2247623919&redirect_uri=http://127.0.0.1:8000/complete/weibo/&state=r3wWt7lw8x1rkXFqum5DW4wibEzbR8oc&response_type=code 类似的地址 输入帐密登录会返回 http://127.0.0.1:8000/index/#/app/home/index 首页。 比较两者回调: - 支付宝回调:支付宝异步POST,需要公网能访问。 - 微博授权回调:登陆后跳转到回调地址,后面加上code等信息,然后code去请求token获取用户信息,相当于已经跳转回本地了。 ### 测试微博认证登录 访问 http://127.0.0.1:8000/login/weibo/ 就可以进入微博认证页面,输入帐密后进入首页。 在数据库中有个 `social_auth_usersocialauth` 表,里面记录了登录用户微博信息 ![BLOG_20191030_113452_98](/media/blog/images/2019/10/BLOG_20191030_113452_98.png "博客图集BLOG_20191030_113452_98.png") 可以看到记录的是`weibo`认证,`uid`以及关联的`user_id`为4 可以查看 `users_userprofile` 表中`id`为4的信息 ![BLOG_20191030_113445_59](/media/blog/images/2019/10/BLOG_20191030_113445_59.png "博客图集BLOG_20191030_113445_59.png") 也就是当使用微博认证登陆后会在Django的用户表中新建一个用户,`username`自动生成唯一字符串。 当下次使用微博认证登录时,会根据 `social_auth_usersocialauth` 表记录的`user_id`查询到 `users_userprofile` 表的用户信息。 刷新 http://127.0.0.1:8000/ 可以看到当前的登录用户 ![BLOG_20191030_113437_70](/media/blog/images/2019/10/BLOG_20191030_113437_70.png "博客图集BLOG_20191030_113437_70.png") 但是在前端登录用户中并不是当前用户 ![BLOG_20191030_113431_77](/media/blog/images/2019/10/BLOG_20191030_113431_77.png "博客图集BLOG_20191030_113431_77.png") Vue前端登录用户名是从`name:cookie.getCookie('name')`获取,并使用`token:cookie.getCookie('token')`去认证,DRF登录实际是使用的Token方式,而Django登录是保存session_id,两者还不互通。下面就开始改造源码了。 ### OAuth结合Token认证登录 #### 分析需要修改的内容 social_django 回调`url(r'^complete/(?P<backend>[^/]+){0}$'.format(extra), views.complete, name='complete'),`这个路由时,调用逻辑源码如下,也就是 PATH/site-packages/social_django/views.py ![BLOG_20191030_113423_23](/media/blog/images/2019/10/BLOG_20191030_113423_23.png "博客图集BLOG_20191030_113423_23.png") 这儿是调用`social_core.actions`中的`do_complete`,可以查看该函数,最后返回`return backend.strategy.redirect(url)`,就可以重写这个地方了。 #### 重写do_complete函数 在Django项目中新建`apps_extend`包,将环境中的 PATH/site-packages/social_core 移动到这个包中 也就是移动下面这个包 ![BLOG_20191030_113411_57](/media/blog/images/2019/10/BLOG_20191030_113411_57.png "博客图集BLOG_20191030_113411_57.png") 移动到 apps_extend 目录下,结构如下 ![BLOG_20191030_113406_99](/media/blog/images/2019/10/BLOG_20191030_113406_99.png "博客图集BLOG_20191030_113406_99.png") 然后修改 DjangoOnlineFreshSupermarket/settings.py ,增加该路径,即将`sys.path.insert(0, os.path.join(BASE_DIR, 'apps_extend'))`添加进入 ```python import os import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, BASE_DIR) sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) sys.path.insert(0, os.path.join(BASE_DIR, 'apps_extend')) # 添加扩展应用路径 ``` 修改 apps_extend/social_core/actions.py 中`do_complete()`函数结尾部分。 参考Vue中注册调用时生成token,并自动登录的过程。参考 https://github.com/davesque/django-rest-framework-simplejwt#creating-tokens-manually 手动生成token(和注册同时登录过程一样),之后将生成的token和用户名放在cookie中。 ```python def do_complete(backend, login, user=None, redirect_name='next', *args, **kwargs): data = backend.strategy.request_data() is_authenticated = user_is_authenticated(user) user = user if is_authenticated else None partial = partial_pipeline_data(backend, user, *args, **kwargs) if partial: user = backend.continue_pipeline(partial) # clean partial data after usage backend.strategy.clean_partial_pipeline(partial.token) else: user = backend.complete(user=user, *args, **kwargs) # pop redirect value before the session is trashed on login(), but after # the pipeline so that the pipeline can change the redirect if needed redirect_value = backend.strategy.session_get(redirect_name, '') or \ data.get(redirect_name, '') # check if the output value is something else than a user and just # return it to the client user_model = backend.strategy.storage.user.user_model() if user and not isinstance(user, user_model): return user if is_authenticated: if not user: url = setting_url(backend, redirect_value, 'LOGIN_REDIRECT_URL') else: url = setting_url(backend, redirect_value, 'NEW_ASSOCIATION_REDIRECT_URL', 'LOGIN_REDIRECT_URL') elif user: if user_is_active(user): # catch is_new/social_user in case login() resets the instance is_new = getattr(user, 'is_new', False) social_user = user.social_user login(backend, user, social_user) # store last login backend name in session backend.strategy.session_set('social_auth_last_login_backend', social_user.provider) if is_new: url = setting_url(backend, 'NEW_USER_REDIRECT_URL', redirect_value, 'LOGIN_REDIRECT_URL') else: url = setting_url(backend, redirect_value, 'LOGIN_REDIRECT_URL') else: if backend.setting('INACTIVE_USER_LOGIN', False): social_user = user.social_user login(backend, user, social_user) url = setting_url(backend, 'INACTIVE_USER_URL', 'LOGIN_ERROR_URL', 'LOGIN_URL') else: url = setting_url(backend, 'LOGIN_ERROR_URL', 'LOGIN_URL') if redirect_value and redirect_value != url: redirect_value = quote(redirect_value) url += ('&' if '?' in url else '?') + \ '{0}={1}'.format(redirect_name, redirect_value) if backend.setting('SANITIZE_REDIRECTS', True): allowed_hosts = backend.setting('ALLOWED_REDIRECT_HOSTS', []) + \ [backend.strategy.request_host()] url = sanitize_redirect(allowed_hosts, url) or \ backend.setting('LOGIN_REDIRECT_URL') # return backend.strategy.redirect(url) # 以下是我们修改的代码 response = backend.strategy.redirect(url) from rest_framework_simplejwt.tokens import RefreshToken import json # 之前代码已经获取了user对象 name = user.name if user.name else user.username # 获取用户名,微博授权登录时,first_name 保存的用户名称,如果获取不到就用username print(name, type(name)) refresh = RefreshToken.for_user(user) access = str(refresh.access_token) # 手动生成token # response.set_cookie('name', name, max_age=24*60*60) # 设置cookie,过期时间为24小时 # 上面直接使用报错UnicodeEncodeError: 'latin-1' codec can't encode characters in position 251-253: ordinal not in range(256) # response.set_cookie('name', name.encode('utf-8').decode('latin-1'), max_age=24 * 60 * 60) # 这种方式不好用,前端不知怎么转换 response.set_cookie('name', json.dumps(name), path='/index', max_age=24 * 60 * 60) # 转换json字符串方式,前端再转回汉字 response.set_cookie('token', access, path='/index', max_age=24*60*60) # 由于Django代理Vue运行后 cookie 保存的路径为 path='/index',所以Django也需要把cookie保存在该路径下 return response ``` 访问 http://127.0.0.1:8000/index/#/app/login 使用Vue自己的登录,cookie保存在`/index`路径下 ![BLOG_20191030_113355_69](/media/blog/images/2019/10/BLOG_20191030_113355_69.png "博客图集BLOG_20191030_113355_69.png") 访问 http://127.0.0.1:8000/login/weibo/ 微博授权登录,也需要将cookie保存在该路径,才能在Vue中操作该cookie,比如退出功能,否则用户退出重新登陆时,不能删除该`name`和`token`导致仍然是登录状态。 ![BLOG_20191030_113349_56](/media/blog/images/2019/10/BLOG_20191030_113349_56.png "博客图集BLOG_20191030_113349_56.png") 所以在上面重写的代码中,**需要设置`path`** #### 没有name字段是显示username 当用户访问 http://127.0.0.1:8000/login/weibo/ 登录认证后,会跳转到首页 这时,左上角显示的用户名为 ![BLOG_20191030_113341_36](/media/blog/images/2019/10/BLOG_20191030_113341_36.png "博客图集BLOG_20191030_113341_36.png") 这是在`name`没有值得情况下显示的 ![BLOG_20191030_113336_23](/media/blog/images/2019/10/BLOG_20191030_113336_23.png "博客图集BLOG_20191030_113336_23.png") 字符串有引号,需要修显示方式,修改 Vue项目 src/store/store.js ```JavaScript function json_to_cn(data) { if (data === '' || data === null){ return ''; } data = JSON.parse(data); // json转为数据 console.log(data); // "\"8b44cf0f8ae34793\"" data = data.replace(/"/g, ''); //取出字符串左右两侧的 " return data; } const userInfo = { //name: cookie.getCookie('name') || '', name: json_to_cn(cookie.getCookie('name')), token: cookie.getCookie('token') || '' }; ``` ![BLOG_20191030_113329_56](/media/blog/images/2019/10/BLOG_20191030_113329_56.png "博客图集BLOG_20191030_113329_56.png") #### 有name字段时显示name,包含中文 可以访问Vue项目 /#/app/home/member/userinfo 修改用户信息 ![BLOG_20191030_113322_54](/media/blog/images/2019/10/BLOG_20191030_113322_54.png "博客图集BLOG_20191030_113322_54.png") 点击提交后,再重新登录 此时用户姓名如下,也不是乱码 ![BLOG_20191030_113317_83](/media/blog/images/2019/10/BLOG_20191030_113317_83.png "博客图集BLOG_20191030_113317_83.png") 再来修改 src/store/store.js 增加转换 ```JavaScript function json_to_cn(data) { if (data === '' || data === null){ return ''; } data = JSON.parse(data); // json转为数据 console.log(data); // "\"8b44cf0f8ae34793\"" 或 "\u8fd9\u662f\u4e2d\u6587" data = data.replace(/"/g, ''); //取出字符串左右两侧的 " if (data.indexOf("\\u") !== -1) { data = data.split("\\u"); let str = ''; for (let i = 0; i < data.length; i++) { console.log(data[i]); if (data[i] !== '') { //console.log(parseInt(data[i], 16).toString(10)); str += String.fromCharCode(parseInt(data[i], 16).toString(10)); } } return str; } else { return data; } } const userInfo = { //name: cookie.getCookie('name') || '', name: json_to_cn(cookie.getCookie('name')), token: cookie.getCookie('token') || '' }; ``` ![BLOG_20191030_113309_87](/media/blog/images/2019/10/BLOG_20191030_113309_87.png "博客图集BLOG_20191030_113309_87.png") 记得将Vue项目重新`> cnpm run build`将 index.entry.js 覆盖到Django项目static下 #### Vue登录页面增加微博认证url 修改 src/views/login/login.vue ,更改微博认证的`href` ```html <ul class="form other-form"> <li> <h5>使用第三方帐号登录</h5> </li> <li class="other-login"> <a class="qq" href="http://xxx/login/qq/"></a> <a class="sina" href="/login/weibo/"></a> <a class="weixin" href="http://xxx/login/weixin/"></a> </li> </ul> ``` 使用 `> cnpm run build` 重新打包存放替换 index.entry.js ![BLOG_20191030_113253_82](/media/blog/images/2019/10/BLOG_20191030_113253_82.png "博客图集BLOG_20191030_113253_82.png") 点击该图标就可以跳转到微博认证界面进行登录返回到主页。 !!!Sentry就不写咯。。。感谢关注

很赞哦! (1)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行546天
  • 系统信息:Linux
  • 后台程序:Python: 3.6.6
  • 网站框架:Django: 2.2.9
  • 文章统计:219 篇
  • 文章评论:37 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 微信公众号:扫描二维码,关注我们
返回
顶部
标题 换行 登录
网站