728x90
소스 다운로드 : https://github.com/armyost/miniterWithPytest.git
armyost/miniter
flask를 사용한 백엔드 1. Contribute to armyost/miniter development by creating an account on GitHub.
github.com
app.py를 실행시키면 완성본이 실행됩니다.
기능은 회원가입, 팔로우/언팔로우, 트윗, 타임라인 입니다.
Python에서 Contoller는 다음과 같이 구현됩니다.
@app.route("/signup",method=['POST'])
def signup():
// 함수정의
Flask가 받은 Json을 파싱하여 사용하는 것은 간단하다.
@app.route("/signup",method=['POST'])
def signup():
new_user = request.json //request.json으로 객체생성 끝
new_user['password'] = bcrypt.hashpw( //password 암호화 하여 저장하기 위함
new_user['password'].encode('UTF-8'), //객체명['key'] 형태로 json데이터 사용
bcrypt.getsalt()
}
JWT(Json Web Token) 을 적용해서 서버사이드 세션을 적용해보자.
@app.route('/login',methods=['POST'])
def login():
credential=request.json
email = credential['email']
password = credential['password']
user_credentail=get_user_id_and_password(email)
if user_credential and bcrypt.checkpw(password.encode('UTF-8'),user_credential['hashed_password'].encode('UTF-8')):
user_id=user_credential['id']
payload={
'user_id':user_id,
'exp':datetime.utcnow()+timedelta(seconds=60*60*24)
} // 페이로드에 user_id와 현재 시간을 포함하여 credential 생성을 위해 jwt 모듈로 보낸다.
token = jwt.encode(payload,app.config['JWT_SECRET_KEY'],'HS256') //jwt 토큰을 생성한다. 사실 여기서 유효시간을 줄 수도 있다.
return jsonify({
'access_token':token.decode('UTF-8')
})
else:
return '',401
if access_token is not None: //Httpie에서 Json으로 access_token이라는 토큰값을 보내줄 경우 라는 뜻이다.
try:
payload = jwt.decode(access_token,current_app.config['JWT_SECRET_KEY'],'HS256') //JWT_SECRET_KEY는 config.py 라는 컨피그 파일에 내가임의의로 입력해놓은 값이다.
except jwt.InvalidTokenError:
payload = None
세션토큰값이 없이(로그인을 하지 않은) 기능으로 접근할때 로그인을 강제하기 위해서는 @wraps와 decorated_function을 사용해야 한다.
데코레이터란?
- 어떤 함수를 받아 명령을 추가한 뒤 이를 다시 함수의 형태로 반환하는 함수.
- 어떤 함수의 내부를 수정하지 않고 기능에 변화를 주고 싶을 때 사용한다.
- 말그대로 다른 함수를 꾸며주는 함수.
def 데코레이터이름(func): # 기능을 추가할 함수를 인자로 받아온다.
def 내부함수이름(*args, **kwargs):
기존 함수에 추가할 명령
return func(*args, **kwargs)
return 내부함수이름
위와 같이 함수를 인자로 받아 무언가를 추가하고 다시 함수로 반환한다.
데코레이터와 wrap으로 구현한 로그인 강제 함수는 다음과 같다.
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
access_token=request.headers.get('Authorization')
if access_token is not None:
try:
payload = jwt.decode(access_token,current_app.config['JWT_SECRET_KEY'],'HS256')
except jwt.InvalidTokenError:
payload = None
if payload is None:return Response(status=401)
user_id=payload['user_id']
g.user_id=user_id
g.user=get_user(user_id) if user_id else None
else:
return Response(status=401)
return f(*args, **kwargs)
return decorated_function
이제 각 기능들에 로그인을 강제할때는 다음과 같은 패턴으로 어노테이션을 해주면 된다.
@app.route('/timeline',methods=['GET'])
@login_required
def user_timeline():
user_id=g.user_id
.
.
.
'Programming > Python' 카테고리의 다른 글
SQLAlchemy Metadata로 테이블, 쿼리 개발. JOIN 샘플 (0) | 2023.10.17 |
---|---|
Python 에서 pip install할때 발생하는 오류들 (0) | 2023.03.21 |
(Python) Pytest로 Unit-test 구현하기 (0) | 2021.05.31 |
깔끔한 파이썬 탄탄한 백엔드 2. HTTP 구조와 이해 - 비제이퍼블릭 (0) | 2021.05.02 |
깔끔한 파이썬 탄탄한 백엔드 1. 환경 설치 - 비제이퍼블릭 (0) | 2021.05.02 |