什么是token?Android中token的使用讲解

 

通过本篇可以基本掌握使用token,下面就来一步一步开始学会使用吧!

Token(计算机术语)

在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。

数据处理

token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。例如在USB1.1协议中定义了4类数据包:token包、data包、handshake包和special包。主机和USB设备之间连续数据的交换可以分为三个阶段,第一个阶段由主机发送token包,不同的token包内容不一样(暗号不一样)可以告诉设备做不同的工作,第二个阶段发送data包,第三个阶段由设备返回一个handshake包。

 

(网络上)基于 Token 的身份验证方法

 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

下面是个人的理解:

1.登录的时候(或者第一次打开APP的时候),登录成功之后,我们需要给他分配一个token。(1)token可以是文件的形式存着;(2)也可以存在数据库,但是存放在数据库,我个人不推荐,因为每次调用api接口都会对比,这样做法会加重服务器压力;(3)用redis存放token。

2.登录之后,我们要返回token,让安卓或者ios去保存这个token,以后每次操作都携带token去请求接口。

3.接下来就是我们要用它传给我们的token去对比,如果符合,那就正常返回数据,否则就返回一个标识,告诉app说这个token不符合,需要重新登录。

 

下面我们来看一下token的具体使用,在开发中我的需求是用户第一次打开我们的APP的时候就获取到一个token,然后保存到本地,这样在下一次打开后我们就能根据token来判断用户的信息(如果用户注册,则把用户信息和token在后台绑定):

1:首先获取token(这里是当打开APP的时候的一个Activity中)

//初始化数据,获得应用的token并且保存
public void initData() {
    //判断有没有旧的token,AndroidFileUtil这个工具类在下面的代码中
    String myToken = AndroidFileUtil.readFileByLines(getCacheDir().getAbsolutePath() + "/" + DataConfig.TOKEN_FILE_NAME);
    if (!TextUtils.isEmpty(myToken)) {
        Log.d("WelcomeActivity","Token: "+myToken);
    } else {
        APIConfig.getDataIntoView(new Runnable() {
            @Override
            public void run() {
                String member = "member";
                Map map = new HashMap<>();
                map.put("grantType", member);
                map.put("token","");
                map.put("appId","");
                map.put("appSecret","");
                //对传入的数据进行加密
                String paramJson = EncryptUtil.encrypt(map);
                //下面的是获取token的服务器地址,项目中应该根据具体的请求地址
                String url = "xxxhttp://45.5.175.255/shop/api/xxxtoken/refresh.do";
                String rs = HttpUtil.GetDataFromNetByPost(url,
                        new ParamsBuilder().addParam("paramJson", paramJson).getParams());
                //对数据进行解密到我们的一个保存token的类中(UserToken类)
                final UserToken result = EncryptUtil.decrypt(rs, UserToken.class);
                if (result != null && result.getResult() == APIConfig.CODE_SUCCESS) {
                    //保存我们获取的token在文件中,方便下次获取,这个工具也在下面
                    APIUtil.saveToken(result.getData());
                } else {
                  //下面的是自己写的一个工具类,也可以用Toast弹窗消息
                    ToastUtil.toastByCode(result);
                }
            }
        });
    }
}

2:加密解密的类(由于是在网络上传送数据,安全性很重要)

public class EncryptUtil {

    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";

    // 加密秘钥
    private static final String AES_KEY = "xxxSuper/168";

    private static SecretKeySpec secretKeySpec;

    /**
     * 前台传输数据解密
     *
     * @param rawJson 原始JSON
     * @return 解密后的Map
     */
      //其中的BaseResult也在下面
    public static  T decrypt(String rawJson, Class tClass) {

        T result=null;

        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, getAesKey());
            byte[] paramBytes = cipher.doFinal(Base64.decode(rawJson.getBytes("UTF-8"), Base64.NO_WRAP));
            String paramJson = new String(paramBytes);
            result = GsonUtil.fromJson(paramJson, tClass);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 数据传输过程中需要加密设置
     * @param rawMap
     * @return
     */

    public static String encrypt(Map rawMap) {
        String result = "";

        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, getAesKey());

            String rawJson = GsonUtil.toJson(rawMap);
            byte[] paramBytes = cipher.doFinal(rawJson.getBytes("UTF-8"));
            result = Base64.encodeToString(paramBytes, Base64.NO_WRAP);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return result;
    }

    private static SecretKeySpec getAesKey() {
        if (secretKeySpec != null) {
            return secretKeySpec;
        }
        try {
            secretKeySpec = new SecretKeySpec(AES_KEY.getBytes("UTF-8"), "AES");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return secretKeySpec;
    }
}

3:参数构造类

public class ParamsBuilder {

    private HashMap params;

    public ParamsBuilder() {

    }

    public ParamsBuilder addParam(String key, String value) {
        if (params == null) {
            params = new HashMap<>();
        }
        params.put(key, value);
        return this;
    }

    public HashMap getParams() {
        return params;
    }
}

4:保存token的类

/**
 * 打开应用就获取到token
 * Created by acer-pc on 2018/7/26.
 */

public class UserToken extends BaseResult {
    private String data;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}

 

5:保存token的工具类:

public class APIUtil {

    public interface CallBack {
        void handleResult(T result);
    }

    /**
     * 保存用户打开APP的时候的token信息
     * @param token 用户
     */
    public static void saveToken(String token) {
        RuntimeConfig.token = token;
        String absolutePath = WinnerApplication.getContext().getCacheDir().getAbsolutePath();
        AndroidFileUtil.writeStringToFile("true", absolutePath, DataConfig.PUSH_FILE_NAME);
        AndroidFileUtil.writeStringToFile(token, absolutePath, DataConfig.TOKEN_FILE_NAME);
        RuntimeConfig.FIRST_STARTUP = true;
    }

}

7:写入到文件中的一个工具类

 

/**
 * Created by acer-pc on 2018/7/26.
 */

public class AndroidFileUtil {


    /**
     * 存储登录token
     *
     * @param string
     * @param filePath
     * @param fileName
     */
    public static void writeStringToFile(String string, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file;
        try {
            file = new File(filePath, fileName);
            if (file.exists()) {
                boolean delete = file.delete();
                LogUtil.i("删除文件", delete + "");
            }

            File dir = new File(filePath);
            if (!dir.exists() && !dir.isDirectory()) {//判断文件夹目录是否存在
                boolean mkdirs = dir.mkdirs();
                LogUtil.i("创建文件夹", mkdirs + "");
            }

            LogUtil.i("token write file path", file.getAbsolutePath());

            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(string.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static void deleteFile(File file) {
        if (file.exists()) {
            boolean delete = file.delete();
            LogUtil.i("删除文件", delete + "");
        }
    }

    /**
     * 删除token
     *
     * @param filePath
     * @param fileName
     */
    private static void deleteToken(File filePath, String fileName) {
        File file = new File(filePath, fileName);
        if (file.exists()) {
            boolean delete = file.delete();
            LogUtil.i("删除token", delete + "");
            if (delete) {
                String absolutePath = WinnerApplication.getContext().getCacheDir().getAbsolutePath();
                AndroidFileUtil.writeStringToFile("true", absolutePath, DataConfig.PUSH_FILE_NAME);
            }
        }
    }

    public static void deleteToken() {
        deleteToken(new File(WinnerApplication.getContext().getCacheDir().getAbsolutePath() + "/"), DataConfig.TOKEN_FILE_NAME);
    }

    /**
     * 读取token
     *
     * @param fileName
     * @return
     */
    public static String readFileByLines(String fileName) {
        LogUtil.i("token read file path: ", fileName);
        File file = new File(fileName);
        BufferedReader reader = null;
        StringBuffer sb = new StringBuffer();
        try {
            if (!file.exists()) {
                return "";
            }
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
                sb.append(tempString);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    /**
     * 
功能简述:4.4及以上获取图片的方法 *
功能详细描述: *
注意: * * @param context * @param uri * @return */ @TargetApi(Build.VERSION_CODES.KITKAT) public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{split[1]}; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { // Return the remote address if (isGooglePhotosUri(uri)) return uri.getLastPathSegment(); return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } } catch (Exception ex) { ex.printStackTrace(); } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */ public static boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); } }

8:其中的BaseResult

**
 * Created by acer-pc on 2018/6/19.
 */

public class BaseResult {

    private int result;
    private String message;

    public int getResult() {
        return result;
    }

    public void setResult(int result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

******************************************补充******************************************

public class RuntimeConfig {

    public volatile static String token="";


}

 

**
 * 存储设置(可以存储用户信息,宝宝信息,用户token等
 * Created by acer-pc on 2018/7/26.
 */

public class DataConfig {
    public static final String TOKEN_FILE_NAME = "info.txt";
  
}
/**
 * 我们的住应用,全局变量,第三方SDK初始化等都在这个类中
 * Created by acer-pc on 2018/6/12.
 */

public class WinnerApplication extends MultiDexApplication {
    public static Activity activity;
    private static WinnerApplication application;
    private Context context;


    @Override
    public void onCreate() {
        super.onCreate();
        application = this;
        context = getApplicationContext();
     
    }

   
    /**
     * 获取到本应用的对象
     */
    public static WinnerApplication getApplication(){
        return application;
    }
    /**
     * 获取上下文
     */
    public static Context getContext(){
        return getApplication().getApplicationContext();
    }
  
}

你可能感兴趣的:(Token)