私はPHP Lumenでログイン時にトークンを返すLumenでアプリを構築しています。これ以上先に進む方法がわかりません。
これらのトークンを使用してセッションを維持するにはどうすればよいですか?
具体的には、reactjsまたはVanilla HTML/CSS/jQueryを使用している場合、クライアント側にトークンを保存し、Webアプリの安全な部分に対して行うすべてのリクエストでトークンを送信するにはどうすればよいですか?
私が通常やることは、トークンをローカルストレージに保持することです。これにより、ユーザーがサイトを離れてもトークンを保持できます。
localStorage.setItem('app-token', theTokenFromServer);
ユーザーがページをロードするたびに、私が最初にすることはトークンの存在を探すことです。
token = localStorage.getItem('app-token');
反応を使用する場合、グローバル状態でトークンを保持します(たとえば、reduxを使用します)。
function loadAppToken(token) {
return {
type: 'LOAD_TOKEN',
payload: { token },
};
}
Vanilla javascriptを使用すると、接続ユーティリティに保持します。次のようになります。
const token = localStorage.getItem('app-token');
export function request(config) {
const { url, ...others } = config;
return fetch(url, {
...others,
credentials: 'include',
headers: {
'Authorization': `Bearer ${token}`
},
});
}
以前のコードと同様に、反応アプリにはまだフェッチユーティリティがありますが、オプションごとにトークンを送信し、リクエストごとにreduxミドルウェアで取得します。
APPをビルドしたいと仮定しましょう。
REST APIを作成するときは、セッションを忘れる必要があります。
REST APIはステートレスであることを意図しているため、セッションに依存してはならず、クライアントから提供されたデータのみでリクエストを処理する必要があります。
クライアントがやりたいのは、トークンのusername
とpassword
を交換することだけです。
これはHTTPリクエストの例です
POST /api/v1/authentication HTTP/1.1
Host: localhost
Content-Type: application/json
{
"username": "foo",
"password": "bar"
}
応答は次のとおりです。
{
"token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
APIが認証リクエストを処理する方法
ユーザー名foo
とパスワードbar
を持つユーザーが見つかり、DBでアクティブかどうかを確認します
JWT(Json Web Token)を生成します
JWTを含む応答を返します
これは、たとえば非常に単純な認証方法です。
public function authAction()
{
/** Get your payload somehow */
$request = $_POST;
//Validate if username & password are given/
$user = $this->model->auth($username, $password);
if(!$user) {
//throw error for not valid credentials
}
$jwt = $this->jwt->create($user);
//return response with $jwt
}
ご覧のとおり、セッションは設定されていません。
クライアント側が応答を処理する方法は?
クライアントは superagent のようなパッケージを使用して、APIへのリクエストとレスポンスを処理します。これにより、プロセスは次のように簡略化されます。
let data = {
username: email,
password: password
};
request
.post('/api/v1/authentication')
.set('Content-Type', 'application/json')
.send(data)
.end(function (error, response) {
//response.body.token
});
generateおよびvalidatingJWTに3RD PTパッケージを使用できます自分で書いてください。
これを見てください package 、それがどのように行われたかを見ることができます。
そして、常に強力な署名を作成することを忘れないでください。 RSA keys
の使用をお勧めします
私はこのプロジェクトを宣伝したりサポートしたりしていません。ここで共有するのが便利だとわかりました。 NodeJSプロジェクトではこれを使用したことはなく、これに似たものを使用しています。
既に知っているように、これらは2つの方法ですlocalStorage
&cookies
私にとっては、私はcookieを使用しています。
しかし、それはすべてあなた次第です。
これからサーバーへのすべてのリクエストで、JWTを含める必要があります。
REST= APIで、JWTを検証し、ユーザーオブジェクトと交換するメソッドを記述する必要があります。
リクエストの例:
let jwt = ...; //GET IT FROM LOCALSTORAGE OR COOKIE
request
.get('/api/v1/posts')
.set('Content-Type', 'application/json')
.set('Authorization', jwt)
.end(function (error, response) {
});
APIがこのリクエストを処理する方法
public function postsAction()
{
$jwt = $this->headers->get('Authorization');
if(!$this->jwt->validate($jwt)) {
//throw unauthorized error
}
$user = $this->model->exchangeJWT($jwt);
//Your logic here
}
Cookieを使用してJWTを保存する場合は、有効期限の設定に注意してください。
Cookieの有効期限はJWTの有効期限と等しくなければなりません。
現在、Lumen for APIを使用して同じタイプのアプリケーションで作業しています。 Lumen with JWT のトークンベースの認証の3つの手順に従います:
1。トークンを作成し、ログイン成功後に戻る
public function login(Request $request) {
$token = $this->jwt->attempt(['user_name' => $data['user_name'], 'password' => $data['password']]); //$token = $this->jwt->attempt($data);
if (!$token) {
$response = array('success' => false, 'data' => null, 'detail' => array('message' => Messages::MSG_INVALID_USER, 'error' => array(Messages::MSG_INVALID_USER)));
return response()->json($response);
} else {
$user = \Auth::setToken($token)->user();
$data = array('token' => $token,'user_id' => $user->id);
$response = array('success' => true, 'data' => $data, 'detail' => array('message' => Messages::MSG_SUCCESS, 'error' => null));
return response()->json($response);
}
}
2。トークン検証用のミドルウェアを定義する
public function handle($request, Closure $next, $guard = null) {
try {
$token = $request->header('X-TOKEN');
$user_id = $request->header('X-USER');
$user = \Auth::setToken($token)->user();
if ($user && $user->id == $user_id) {
return $next($request);
} else {
$response = array('success' => false, 'data' => null, 'detail' => array('message' => Messages::MSG_ERR_INVALID_TOKEN, 'error' => Messages::MSG_ERR_INVALID_TOKEN));
return response()->json($response);
}
} catch (Exception $ex) {
$response = array('success' => false, 'data' => null, 'detail' => array('message' => Messages::MSG_ERROR_500, 'error' => array($ex)));
return response()->json($response);
}
}
3。 localstorageまたはcookieにトークンを保存します
localStorage.setItem("Token", JSON.stringify(TokenData));
TokenData = JSON.parse(localStorage.getItem("Token"));
または
$.cookie('Token', JSON.stringify(TokenData), {expires: 1, path: '/'});
TokenData = JSON.parse($.cookie("Token"));
4。ヘッダーのすべてのリクエストでトークンを送信します
カスタムヘッダー付きのリクエスト
$.ajax({
url: 'foo/bar',
headers: { 'X-TOKEN': TokenData.Token ,'X-USER': TokenData.UserId}
});
すべてのリクエストへのヘッダー
$.ajaxSetup({
headers: { 'X-TOKEN': TokenData.Token ,'X-USER': TokenData.UserId}
});
それが役立つことを願っています。
注:localstorage
またはcookies
からデータを読み取りながら、いくつかのチェックとデータ検証を追加します。
ブラウザのlocalStorageに保存し、サーバーへの各リクエストのヘッダーに設定できます。
暗号化と復号化のために、構築されたlaravelの暗号モデルで使用できます
Illuminate\Support\Facades\Cryptを使用
APIトークンを生成するために行うことは、必須フィールドの配列を取ります。
データを作成しましょう
$data = [
'user_id' => $user->id,
'time_stemp' => \Carbon::now() // Carbon is laravel's time model(class) for managing times
'expire_on' => \Carbon::now()->addDays(2); //here i'm setting token expires time for 2 days you can change any
];
$data = serialize($data);
次に、Cryptでデータを暗号化します
$accessToken = Crypt::encrypt($data);
応答としてフロントエンドに送信し、ローカルストレージまたはCookieに保存します。ここで時間の必要のないものはすべて、サーバーでのみチェックします。
これで、すべてのリクエストでそのトークンを渡し、サーバー側でデータを解析するミドルウェアを1つ作成し、トークン時間が短い場合は期限切れになり、それ以外の場合はエラー403または必要なものを送信します。
サーバー側でデータを解析する方法
コマンドを使用してミドルウェアを作成します:php artisan make:middleware ApiAuth then is handle part
//Accesstoken you passed in $headers or in $request param use whatever you like
$searilizerData = Crypt::decrypt($headers['AccessToken']);
$data = unserialize($searilizerData);
//check if expire_on is less then current server time
if($data['expire_on] <= \Curbon::now()){
next(); // let them contuine and access data
} else {
throw new Exception ("Your token has expired please regenerate your token",403);
}
これが役立つことを願っています:)
実際には、ReactJSやVanillaJSは必要ありません。純粋なHTMLとPHP実際。私がしているのは、それをCookieとして保存することです。
まず、Lumenからトークンを受け取ったら、特定のユーザーのユーザーデータベースにトークンを保存します。次に、ユーザーIDとaccesstokenをCookieとして設定します。Cookieは、次のコードを使用して一定時間後に有効期限が切れます。
setcookie('userid',$userid, time()+(3600 * 24 * 15),"/");
setcookie('accesstoken',$accesstoken, time()+(3600 * 24 * 15),"/");
header('Location: /home.php');
//You can change the 15 in setcookie() to amount of days the cookie will expire in.
//The "/" in setcookie is important, because it ensures the cookies will be available on every page the user visits on your website.
//The header function redirects to your home page after log in
次に、ホームページがどのように表示されるかを示します。 accesstoken cookieが存在するかどうかを確認し、存在する場合は、トークンがユーザーデータベース内の現在のトークンと一致することを二重に確認します。一致する場合は、「ログイン」ページが表示されます。そうでない場合は、ログインページを表示/リダイレクトする必要があります。
<?php
if (isset($_COOKIE['accesstoken']))
{
//connect to your user database and check that the cookie accesstoken matches
// if it doesn't match, deal with it appropriately, such as deleting all cookies then redirecting to login page.
}
?>
<!DOCTYPE HTML>
<html>
<head>
<title>Sup</title>
</head>
<body>
<?php if (isset($_COOKIE['accesstoken'])){ ?>
<h1>User logged in!</h1>
<h3>Do whatever you need to do if user is logged in</h3>
<?php } else { ?>
<h1>No accesstoken found</h1>
<h3>More than likely you will want to show login page here</h3>
<?php } ?>
</body>
</html>
ログアウトするのは簡単です。以下のコードは、アクセストークンを期限切れに設定して削除します。
setcookie("accesstoken", "", time() - 3600);
setcookie("userid", "", time() - 3600);
header('Location: /youareloggedout.html');
これは、機能的なログイン/ログアウトシステムの基本であることに注意してください。必要なすべてのセキュリティ対策を説明すると、この投稿はさらに長くなります。必ず調査を行ってください。始めるためのいくつかのトピックは、準備されたステートメントとXSS攻撃の防止です。 :)
最近、JWTを使用してユーザーのセッションを開始、維持、および期限切れにする反応Webポータルを終了しました。
コードスニペット
ログインAPI呼び出しからトークンを取得したと仮定します。
セッションストレージと状態にトークンを設定します(reduxストア)
window.sessionStorage.setItem('partyToken', token)
store.dispatch({type: 'profile/setToken', payload: { token }})
セッションストレージまたは状態からのトークンの取得(reduxストア)
const token = window.sessionStorage.getItem('token')
const token = store.getState().profile && store.getState().profile.token
もちろん、API呼び出しごとにトークンを設定/更新できる共通の関数を定義できます。 API呼び出しを行う前にトークンが必要になるため、取得についても同様です。
コードでそれを行うには多くの方法があるので、簡単な作業とベストプラクティスを書き留めます。
ログインリクエスト、{メール、パスワード}を渡します。
成功したら、トークンを取得してローカルに保存します。localstorageが推奨されますが、Cookieも使用できます。
反応アプリでページをロードするたびに、そのトークンの機能チェックを行う必要があります。トークンは復号化され、さらに使用するために詳細を取得します。
ユーザー名、ユーザーIDなどを取得することを意味します。追加する場合は「有効期限」が重要です。トークンの有効期限が切れた場合、ユーザーをログインページにリダイレクトしますOR you新しいトークンを再リクエストできます。アプリによって異なります。
ログアウトは非常に簡単です...単にクライアント側からトークンを削除し、ログインページにリダイレクトします。
「認証された」ページでは、トークンが存在することを確認し、さらにユーザータイプを確認できることを確認してください。
** JWTのクライアント側のデコードには、次を使用できます。 https://www.npmjs.com/package/jwt-client