About the use of Token to realize user login in Android
principle
Token is generally used to realize user login in Android. At present, the most popular method is to use jwt. Let's talk about the implementation principle first: Step 1: when the user logs in for the first time, the client sends the user and password to the server, and the server verifies whether the user password is correct. If it is incorrect, a message (wrong user name or wrong password) will be returned to the client. If it is correct, The server generates a token and caches it (Redis or database can be used). Step 2: the client receives the token sent by the server and the identification of successful login, saves the token, and jumps to the page after successful login. Step 3: after successful login, other requests for data from the server will always carry the token saved by the client in the request header. The server will verify whether the token carried by these requests is expired or incorrect. If it is normal, it will return the normal data. If it fails, it will return the information of failure to verify the token. The customer service will receive the failed information and prompt the user to log in again, And jump to the login page.
flow chart
Reception
Step 1: when the user logs in for the first time, the client sends the user and password to the server,
try{ String loginurl = getString(R.string.url2) + "login"; //Write your own tool class YyHttpRequestOrGetDataFromNet yyHttpRequestOrGetDataFromNet = new YyHttpRequestOrGetDataFromNet(); //The following method is to put accountid and credential into the JsonObject object, // Because the parameter set in the background / 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 to the server locally // json formatting jsonLoginningInfo = yyHttpRequestOrGetDataFromNet.doPost(loginurl,jsonParam); Gson gson = new Gson(); jsonRootBean = gson.fromJson(jsonLoginningInfo,new TypeToken<JsonRootBean>(){}.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();} //Correct password: the server returns 1 if (jsonRootBean.getStatus()==0&&jsonRootBean.getMsg().equals("loginSuccess")) { Toast.makeText(this, "Login successful", Toast.LENGTH_SHORT).show(); YySharedPrefUtility.setParam(LoginActivity.this, YySharedPrefUtility.ACCOUNTID, accountid);//Save the user name startActivity(new Intent(getApplicationContext(), MainActivity.class));//Log in successfully and jump to the home page } //User name does not exist or password error: the server returns - 1 else { Toast.makeText(this, "The user name does not exist or the password is incorrect", Toast.LENGTH_SHORT).show(); }
This is the tool class I changed
post request:
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 //See the original blog https://blog.csdn.net/yuan882696yan/article/details/38419219 StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); //Create URL connection URL localURL = new URL(url); URLConnection connection = this.openConnection(localURL); HttpURLConnection httpURLConnection = (HttpURLConnection) connection; httpURLConnection.setDoOutput(true); httpURLConnection.setRequestMethod("POST");//The 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); //The key to this place is to log in to the account and password passed over outputStreamWriter.write(jsonParam.toString()); outputStreamWriter.flush(); //Judge whether the request is successful if (httpURLConnection.getResponseCode() >= 300) { throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode()); } //Receive response flow 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 request:
//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 url url = new URL(u); //Get HttpURLConnection HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //Set get request connection.setRequestMethod("GET"); //Set timeout connection.setConnectTimeout(5 * 1000); //Set encoding connection.setRequestProperty("contentType", "utf-8"); //Note that the most important thing is to put the Token in the request header through setRequestProperty connection.setRequestProperty("token",token); //connect connection.connect(); //Get connection response code int code = connection.getResponseCode(); //Response failed if (code >= 300) { throw new Exception("HTTP Request is not success, Response code is " + code); } //If connected if (code == 200) { // h.sendEmptyMessage(2); //get 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 connection connection.disconnect(); } catch (Exception e) { e.printStackTrace(); } } }); newThread.start(); //Start thread try { //join method: let the main thread wait for the child thread to run before continuing newThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } return jsonBuffer; }
backstage
1. Interceptor: every request sent by the client to the server must be verified here. If the Token is invalid or forged, it will be verified and return the client error information
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 validation 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 tools
public class JWTUtils { token secret key(custom),It's best to generate a random string online. I hit it blindly here //This key must not be compromised private static final String SING = "!@#$%%^&&*####%%%$%"; //Generate Token public static String getToken(Map<String,String> map){ Calendar instance = Calendar.getInstance(); instance.add(Calendar.HOUR,5); JWTCreator.Builder builder = JWT.create(); map.forEach((k,v)->{ builder.withClaim(k,v); }); String token = builder.withExpiresAt(instance.getTime()) .sign(Algorithm.HMAC256(SING)); return token; } //Generate JWT validator based on key public static void verify(String token){//Parse Token JWT.require(Algorithm.HMAC256(SING)).build().verify(token); } //Validate TOKEN public static DecodedJWT getTokenInfo(String token){ return JWT.require(Algorithm.HMAC256(SING)).build().verify(token); } }
3.spring.mvc is written on the outside of the tag. Because the client needs to obtain the Token through / login, it cannot be intercepted
<!-- Configuring Interceptors ,verification Token --> <mvc:interceptors> <mvc:interceptor> <!-- Intercept all/Page below directory --> <mvc:mapping path="/**"/> <!-- mvc:exclude-mapping It is another kind of interception, which can not intercept a page in your later tests --> <mvc:exclude-mapping path="/login" /> <bean class="com.yunyou.DBI.interceptor.JWTInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
4.controller layer
For other service layers, there is no need to give entity classes. Here is a control layer
@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<String,String> payload = new HashMap<String,String>(); payload.put("accountid", us.getAccountid()); String token = JWTUtils.getToken(payload); LoginToken loginToken = new LoginToken(); loginToken.setToken(token); uJsonBaseObject.setContent(loginToken); uJsonBaseObject.setMsg("loginSuccess"); return uJsonBaseObject; }
Finally