アンドロイドにおけるトークンの利用
2022-02-18 13:05:45
Androidでユーザーログインを実現するためのTokenの利用について
原理
Androidでは、ユーザーログインはTokenを使うのが一般的で、jwtを使うのが主流です。 まず、実装原理についてですが、ユーザーが初めてログインするとき、クライアントはユーザーとパスワードをサーバーに送信し、サーバーはユーザーのパスワードが正しいかどうかを検証し、正しくない場合はクライアントにメッセージ(ユーザー名エラー、パスワードエラー)を返し、正しい場合は、サーバーがTokenを生成し、キャッシュ(Redisでもデータベースでも可)しておくというものです。ステップ2:クライアントは、サーバーからTokenとログイン成功のトークンを受け取り、Tokenも保存し、ログイン成功のページにジャンプする。ステップ3:ログイン成功後、サーバからの他のデータ要求があり、全てリクエストヘッダにクライアントが保存したTokenを運び、サーバはこれらの要求で運ばれたTokenが期限切れか不正かを検証し、正常なら通常のデータを返し、Tokenの検証に失敗したら失敗のメッセージを返し、クライアントが失敗メッセージを受け取った場合は再ログインを促してログインページへジャンプする。
フローチャート
前景
ステップ1:ユーザーが初めてログインするとき、クライアントはユーザーとパスワードをサーバーに送信する
try{
String loginurl = getString(R.string.url2) + "login";
// Write your own tool class
YyHttpRequestOrGetDataFromNet yyHttpRequestOrGetDataFromNet = new YyHttpRequestOrGetDataFromNet();
// The following is used to put the accountid and credential into the JsonObject object.
// because the parameters set by backend/login is a user object
JSONObject jsonParam = new JSONObject();
jsonParam.put("credential", password);
jsonParam.put("accountid", accountid);
// System.out.println("token:"+yyHttpRequestOrGetDataFromNet.doPost(loginurl,jsonParam));
// store the Token generated by the first login server locally
// json formatting
jsonLoginningInfo = yyHttpRequestOrGetDataFromNet.doPost(loginurl,jsonParam);
Gson gson = new Gson();
jsonRootBean = gson.fromJson(jsonLoginningInfo,new TypeToken
(){}.getType());
//token storage
YySharedPrefUtility.setParam(LoginActivity.this,YySharedPrefUtility.Token,
jsonRootBean.getContent().getToken());
System.out.println("tokrn:"+jsonRootBean.getContent().getToken());
System.out.println("tokrn:"+jsonRootBean.getMsg());
}
catch (Exception e){ e.printStackTrace();}
// The password is correct: the server returns 1
if (jsonRootBean.getStatus()==0&&jsonRootBean.getMsg().equals("loginSuccess")) {
Toast.makeText(this, "loginSuccess", Toast.LENGTH_SHORT).show();
YySharedPrefUtility.setParam(LoginActivity.this,
YySharedPrefUtility.setParam(LoginActivity.this, YySharedPrefUtility.ACCOUNTID, accountid);//Save the username
startActivity(new Intent(getApplicationContext(), MainActivity.class));//login successfully jump to home page
}
//Username does not exist or password is wrong: -1 is returned by the server
else {
Toast.makeText(this, "Username does not exist or password is incorrect", Toast.LENGTH_SHORT).show();
}
これは、私が変更したツールクラスです。
ポストリクエスト
public String doPost(String url, JSONObject jsonParam) throws Exception {
/* Translate parameter map to parameter date string */
System.out.println("POST parameter : " + jsonParam.toString());
// The following two lines of code are very useful and are a strict format for network connections
// The original blog is available at https://blog.csdn.net/yuan882696yan/article/details/38419219
StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
// Create a URL connection
URL localURL = new URL(url);
URLConnection connection = this.openConnection(localURL);
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");//request method is Post
httpURLConnection.setRequestProperty("Accept-Charset", charset);
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setUseCaches(false);//post cannot set cache
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
try {
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
// This is the most critical place, the account and password that will be passed to the login
outputStreamWriter.write(jsonParam.toString());
outputStreamWriter.flush();
// determine if the request is successful
if (httpURLConnection.getResponseCode() >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
// Receive the response stream
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
reader = new BufferedReader(inputStreamReader);
while ((tempLine = reader.readLine()) ! = null) {
resultBuffer.append(tempLine);
}
} finally {
if (outputStreamWriter ! = null) {
outputStreamWriter.close();
}
if (outputStream ! = null) {
outputStream.close();
}
if (reader ! = null) {
reader.close();
}
if (inputStreamReader ! = null) {
inputStreamReader.close();
}
if (inputStream ! = null) {
inputStream.close();
}
}
return resultBuffer.toString();//return data
}
リクエストを取得します。
// Get JSON data stream data
public static String doGetJsonStringFromThread(final String u,final String token) {
Thread newThread;
newThread = new Thread(new Runnable() {
@Override
public void run() {
// Create url object
URL url = null;
try {
//Instantiate the url
url = new URL(u);
//get HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//set the get request
connection.setRequestMethod("GET");
//set the timeout
connection.setConnectTimeout(5 * 1000);
//set the encoding
connection.setRequestProperty("contentType", "utf-8");
// Note that the most important thing is to put the Token in the request header via setRequestProperty
connection.setRequestProperty("token", token);
//connect
connection.connect();
//Get the connection response code
int code = connection.getResponseCode();
// response failure
if (code >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + code);
}
//If connected
if (code == 200) {
// h.sendEmptyMessage(2);
// Get the data
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuffer buffer = new StringBuffer();
while ((line = bufferedReader.readLine()) ! = null) {
buffer.append(line);
}
//get json
jsonBuffer = buffer.toString();
//close is
inputStream.close();
}
//close the connection
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
});
newThread.start(); //start the thread
try {
//join method: let the main thread wait for the child thread to finish running before continuing
newThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return jsonBuffer;
}
バックエンド
1. インターセプターです。クライアントからサーバーに送信されるすべてのリクエストはここで検証され、トークンが無効であるか、偽造されたトークンの場合は、クライアントにエラーメッセージを返すために検証されます。
public class JWTInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException{
// TODO Auto-generated method stub
String token = request.getHeader("token");
try{
JWTUtils.verify(token);
return true;
}catch (Exception e){
JsonRootBean sJsonBaseObject=new JsonRootBean();
sJsonBaseObject.setMsg("Token authentication failed");
sJsonBaseObject.setStatus(-1);
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(sJsonBaseObject);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(result);
return false;
}
}
}
2. jwt ツールクラス
public class JWTUtils {
token key (custom), it is best to generate a random string online, I am blindly typed here
// This key must not be leaked
private static final String SING = "! @#$%%^&&*####%%%$%";
//generate Token
public static String getToken(Map
3. spring.mvc is written on the outside of the tag, because the client has to get the Token via /login, so it can't be intercepted
4. controller layer
Other service layers and so on, entity classes are not necessary to give out, a control layer is given here
@Controller
public class UserLoginningInfoController {
@Autowired
private UserLoginningInfoService uService;
@RequestMapping(value="login",method=RequestMethod.POST)
@ResponseBody
public JsonRootBean login(@RequestBody v_U_userLoginning_info user) {
System.out.println("user"+user.getAccountid()+" "+user.getCredential());
JsonRootBean uJsonBaseObject = new JsonRootBean();
v_U_userLoginning_info us = uService.findUserByPassword(
user.getAccountid(), user.getCredential());
if(us==null) {
uJsonBaseObject.setMsg("loginError");
uJsonBaseObject.setStatus(-1);
return uJsonBaseObject;
}
HashMap
And finally it's done
関連
-
NetworkOnMainThreadException
-
AndroidでAttempt to invoke virtual method... on null object referenceの例外が発生する。
-
Gradle のエラーです。gradle-core.jar (com.android.tools.build:gradle-core:x.x.x) を見つけられませんでした。
-
Android studioのインストールと問題発生、Emulator: PANIC: AVDのシステムパスが見つかりません。
-
指定された子にはすでに親がいます。まず、その子の親に対して removeView() をコールする必要があります。
-
ConstraintLayoutのいくつかのプロパティの概要(RelativeLayoutの強化版、LinearLayoutの比例プロパティを含む、階層ツールの削減)。
-
android bluetooth--Bluetooth on、検索、ペアリング、接続
-
Androidの美しいSeekBarスタイルのカスタマイズ
-
android.content.ActivityNotFoundException を解決します。Intent問題を処理するActivityが見つからない
-
AndroidサポートデザインライブラリのFloatingActionButtonについて
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
AndroidStudio reports Could not resolve all artifacts for configuration ':app:classpath'.
-
Android Studio を 3.6.3 にアップデートした後、構成 :classpath のアーティファクトをすべて解決できない。
-
AndroidがMainActivityが包含クラスでないというエラーを報告する
-
Android: インポートモジュールエラー Android リソースのリンクに失敗しました
-
android:EMSのプロパティ
-
Google PlayデバイスはPlay保護機構の認証を受けていません。
-
Android Get set image.setImageResource(R.drawable.xxx) リソース
-
Android--shape--描画のコーナー、グラデーション、パディング、サイズ、ソリッド、ストロークのプロパティを指定する。
-
Android studio 制約レイアウト ConstraintLayout
-
Android ANR traces.txt ファイルエクスポート解析