1. ホーム
  2. android

アンドロイドにおけるトークンの利用

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