前提:由于现有框架已经形成,但是需要增加在每次调用api的时候,进行token认证,认证通过才能允许访问接口。以防止越权访问。所以,准备在代价最小的情况下,进行修改。
总体思路:
详细设计:
一,新建数据库表
数据库新增一张USER_AUTHORITY表,用于存储用户id和对于的密码序列,不必担心数据量大,在用户退出删除该记录,在用户登录之前,会重置一次该序列。
表结构很简单,如下:
二,密码序列的生成
对于密码序列的生成,这里是截取UUID的前八位,然后需要的长度是在调用的时候输入(当然,你可以把这个长度设置放到数据库或者配置文件里,如果以后不够,可以轻松的增长。 )。如下:
private static Set<String> productAuthoritys(int num){
Set<String> setString = new TreeSet<String>();
for(int i = setString.size() ;i<num;i++) {
setString.add(UUID.randomUUID().toString().replace("-", "").substring(0, 8));
}
return setString;
}
这里直接明文返回给app端即可,因为app端会对此密码进行再加密后使用。
三,APP存储密码序列
登录成功后,app对获取到的密码序列进行存储,这里使用的是AsyncStorage存储到本地。
由于AsyncStorage存储的是字符串,故这里做了一点转换。
AsyncStorage.setItem("AuthorityPools", JSON.stringify(responseData.AuthorityPools).replace(/"/g,"").replace("[","").replace("]",""), function (error) {
if (error) {
alert('存储失败');
} else {
console.log('chenggong');
}});
四,请求header中加入token
在每次访问时,header里面加入token。
每次需要获取新的authorityCode加入token中,(此处DES为加密方法,这里每个人的DES均不同,就不贴了,如有需要,可以留言或联系我)。
//通用请求中header
const _getHeader = () => {
const authorityCode = getServerTime();
//未加密前的数据
let proCode = DES.encryptForToken(AppStore.getUserID());
let token = DES.encryptForToken(this.authorityCode + '@' + proCode);
return {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded;application/json;',
'Token': token,
};
};
成功之后,会把该AuthorityPools(密码序列) 中的一个authorityCode拿出来进行使用,然后删除该authorityCode后重新存储。
//授权码
this.authorityCode = "";
function getServerTime() {
//调用接口增加 token ,从本地存储获取,避免越权。
let AuthorityPools = AsyncStorage.getItem('AuthorityPools', function (error, result) {
result = result == null ? "" :result;
this.authorityCode = result.split(",")[0];
AsyncStorage.setItem("AuthorityPools", result.replace(this.authorityCode + ",", ""), function (error) {
if (error) {
Alert.alert(
'错误',
'获取token数据失败',
[
{
text: '重新登录',
onPress: () => AppDispatcher.dispatch({actionType: AppConstants.FORCE_LOGOUT}),
type: 'plain-text'
},
{text: '取消', onPress: () => console.log('取消'), style: 'cancel'}
]
);
} else {
console.log('get authorityCode success!');
}
});
})
return AuthorityPools;
}
五,服务端Filter进行拦截校验。
这里,可以对get进行进行放行,只拦截除了get以外的请求。如下,获取header中token。
String token = DES.quickDecrypt(req.getHeader("Token") == null ? "" : req.getHeader("Token"))
.toLowerCase().trim();
此后,就取出数据库中该用户的密码序列进行比较,比较成功后,放行,不成功则拒绝访问。
注:用户id取决于token中携带的用户id而不是session中的id。
六,可能会遇到的问题
1,由于AsyncStorage是异步存储,可以会出现上一次访问的密码序列,在本次才会进行调用。我这里的解决方案是在登录成功后,任意调用一个get接口一次即可解决异步。当然,还有async/await 的方式,但我试了没有用,可能我版本太低。
总结,这个方案搞了三天,之前走了很多弯路子。如每次访问之前请求一次时间戳(太卡,而且请求是回调请求,获取的时间戳不同步。)
此方案可以说很好的解决了我的问题,此外还有其他的加密方式,如JWT,但是JWT不能实时的变化,如果该访问被拦截后,使用该Token可以继续进行访问。
Bingo~
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!