我正在为整个应用程序使用webapp2身份验证系统。因此,我尝试将其重新用于Google Cloud身份验证,然后知道了!
webapp2_extras.auth使用webapp2_extras.sessions存储身份验证信息。而且,该会话可以以3种不同的格式存储:securecookie,数据存储或内存缓存。
Securecookie是我正在使用的默认格式。我认为它非常安全,因为webapp2 auth系统已用于生产环境中运行的许多GAE应用程序。
因此,我解码了这个securecookie并从GAE端点重用了它。我不知道这是否会产生一些安全问题(我希望不是),但也许@bossylobster可以说看安全方面是否可以。
我的Api:
import cookieimport loggingimport endpointsimport osfrom google.appengine.ext import ndbfrom protorpc import remoteimport timefrom webapp2_extras.sessions import SessionDictfrom web.frankcrm_api_messages import IdContactMsg, FullContactMsg, ContactList, SimpleResponseMsgfrom web.models import Contact, Userfrom webapp2_extras import sessions, securecookie, authimport config__author__ = 'Douglas S. Correa'TOKEN_ConFIG = { 'token_max_age': 86400 * 7 * 3, 'token_new_age': 86400, 'token_cache_age': 3600,}SESSION_ATTRIBUTES = ['user_id', 'remember','token', 'token_ts', 'cache_ts']SESSION_SECRET_KEY = '9C3155EFEEB9D9A66A22EDC16AEDA'@endpoints.api(name='frank', version='v1', description='FrankCRM API')class FrankApi(remote.Service): user = None token = None @classmethod def get_user_from_cookie(cls): serializer = securecookie.SecurecookieSerializer(SESSION_SECRET_KEY) cookie_string = os.environ.get('HTTP_cookie') cookie = cookie.Simplecookie() cookie.load(cookie_string) session = cookie['session'].value session_name = cookie['session_name'].value session_name_data = serializer.deserialize('session_name', session_name) session_dict = SessionDict(cls, data=session_name_data, new=False) if session_dict: session_final = dict(zip(SESSION_ATTRIBUTES, session_dict.get('_user'))) _user, _token = cls.validate_token(session_final.get('user_id'), session_final.get('token'), token_ts=session_final.get('token_ts')) cls.user = _user cls.token = _token @classmethod def user_to_dict(cls, user): """Returns a dictionary based on a user object. Extra attributes to be retrieved must be set in this module's configuration. :param user: User object: an instance the custom user model. :returns: A dictionary with user data. """ if not user: return None user_dict = dict((a, getattr(user, a)) for a in []) user_dict['user_id'] = user.get_id() return user_dict @classmethod def get_user_by_auth_token(cls, user_id, token): """Returns a user dict based on user_id and auth token. :param user_id: User id. :param token: Authentication token. :returns: A tuple ``(user_dict, token_timestamp)``. Both values can be None. The token timestamp will be None if the user is invalid or it is valid but the token requires renewal. """ user, ts = User.get_by_auth_token(user_id, token) return cls.user_to_dict(user), ts @classmethod def validate_token(cls, user_id, token, token_ts=None): """Validates a token. Tokens are random strings used to authenticate temporarily. They are used to validate sessions or service requests. :param user_id: User id. :param token: Token to be checked. :param token_ts: Optional token timestamp used to pre-validate the token age. :returns: A tuple ``(user_dict, token)``. """ now = int(time.time()) delete = token_ts and ((now - token_ts) > TOKEN_CONFIG['token_max_age']) create = False if not delete: # Try to fetch the user. user, ts = cls.get_user_by_auth_token(user_id, token) if user: # Now validate the real timestamp. delete = (now - ts) > TOKEN_CONFIG['token_max_age'] create = (now - ts) > TOKEN_CONFIG['token_new_age'] if delete or create or not user: if delete or create: # Delete token from db. User.delete_auth_token(user_id, token) if delete: user = None token = None return user, token @endpoints.method(IdContactMsg, ContactList,path='contact/list', http_method='GET',name='contact.list') def list_contacts(self, request): self.get_user_from_cookie() if not self.user: raise endpoints.UnauthorizedException('Invalid token.') model_list = Contact.query().fetch(20) contact_list = [] for contact in model_list: contact_list.append(contact.to_full_contact_message()) return ContactList(contact_list=contact_list) @endpoints.method(FullContactMsg, IdContactMsg,path='contact/add', http_method='POST',name='contact.add') def add_contact(self, request): self.get_user_from_cookie() if not self.user:raise endpoints.UnauthorizedException('Invalid token.') new_contact = Contact.put_from_message(request) logging.info(new_contact.key.id()) return IdContactMsg(id=new_contact.key.id()) @endpoints.method(FullContactMsg, IdContactMsg,path='contact/update', http_method='POST',name='contact.update') def update_contact(self, request): self.get_user_from_cookie() if not self.user:raise endpoints.UnauthorizedException('Invalid token.') new_contact = Contact.put_from_message(request) logging.info(new_contact.key.id()) return IdContactMsg(id=new_contact.key.id()) @endpoints.method(IdContactMsg, SimpleResponseMsg,path='contact/delete', http_method='POST',name='contact.delete') def delete_contact(self, request): self.get_user_from_cookie() if not self.user:raise endpoints.UnauthorizedException('Invalid token.') if request.id: contact_to_delete_key = ndb.Key(Contact, request.id) if contact_to_delete_key.get(): contact_to_delete_key.delete() return SimpleResponseMsg(success=True) return SimpleResponseMsg(success=False)APPLICATION = endpoints.api_server([FrankApi], restricted=False)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)