android实现登录一次,之后不需要登录的方法token,session,sharedpreference

        最近,比赛中需要做一个android+后端开发的项目,突然遇到了一个问题,就去百度了下,查了好久,说法不一,最终终于找到了完美的解答,问题描述如下:

        项目要求android端游客可以随意使用很多板块,但有些板块需要登录,只要用户登录后其余地方就不需要登录了。

        一开始,想到了web层的session,所以查了下,有人说可以,就是这么用,但后来又查到了sharedpreference和token,这就让我犯难,到底是什么,于是仔细研究了下,终于明白直接的关系了。

首先说答案吧,android端使用的是token验证。每次带着token去访问。

一、session

session不再多说,主要是web端的会话保存,在android中token去替代了

二、sharedpreference(最好不要用来存用户名和密码,xml文件保存,可以直接查看)

Preperences 是一种应用程序内部轻量级的数据存储方案。Preferences主要用于存储和查询简单数据类型的数据,这些简单数据类型包括boolean、int、float、long以及 String 等,存储方式以键值对的形式存放在应用程序私有的文件夹下。     
      Preferences 一般用来存储应用程序的设置信息,如应用程序的色彩方案、文字字体等。在应用程序中获取Preferences的方式有如下两种。      
      调用Context 对象的 getSharedPreferences 方法获得SharedPreferences 对象。需要传入SharedPreferences 的名称和打开模式,名称为 Preferences 文件名称,如果不存在则创建一个以传入名称为名的新的 Preferences文件;打开模式为 PRIVATE、 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 其中之一。      
     调用Activity对象的 getPreferences 方法获得 SharedPreferences对象。需要传入打开模式,打开模式为 PRIVATE、 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE其中之一。 
     两种获得SharedPreferences 对象的最大的不同就是通过 Context对象 的getSharedPreferences方法获得的对象可以被同一应用程序下的其他组件共享,而是用Activity对象 的getPreferences 方法获得的对象只能被调用该方法所在的Activity使用。 
      SharedPreferences 对象中提供了一系列的 get 方法用于接收键返回对应的值。如果需要对Preferences 文件中存储的键值进行修改,首先需要调用 SharedPreferences的 edit 方法获得一个Editor 对象,该对象可以用来修改 Preferences 文件中存储的内容。下面通过一个小例子来说明 Preferences 的用法。 

三、token

1、Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
2、Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
3、使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
二、如何使用Token?
1、用设备号/设备mac地址作为Token(推荐)
客户端:客户端在登录的时候获取设备的设备号/mac地址,并将其作为参数传递到服务端。
服务端:服务端接收到该参数后,便用一个变量来接收同时将其作为Token保存在数据库,并将该Token设置到session中,客户端每次请求的时候都要统一拦截,并将客户端传递的token和服务器端session中的token进行对比,如果相同则放行,不同则拒绝。
分析:此刻客户端和服务器端就统一了一个唯一的标识Token,而且保证了每一个设备拥有了一个唯一的会话。该方法的缺点是客户端需要带设备号/mac地址作为参数传递,而且服务器端还需要保存;优点是客户端不需重新登录,只要登录一次以后一直可以使用,至于超时的问题是有服务器这边来处理,如何处理?若服务器的Token超时后,服务器只需将客户端传递的Token向数据库中查询,同时并赋值给变量Token,如此,Token的超时又重新计时。
2、用session值作为Token
客户端:客户端只需携带用户名和密码登陆即可。
服务端:服务端接收到用户名和密码后并判断,如果正确了就将本地获取sessionID作为Token返回给客户端,客户端以后只需带上请求数据即可。
分析:这种方式使用的好处是方便,不用存储数据,但是缺点就是当session过期后,客户端必须重新登录才能进行访问数据。
实现:
通过使用session以及在session中加入token,来验证同一个操作人员是否进行了并发重复的请求,在后一个请求到来时,使用session中的token验证请求中的token是否一致,当不一致时,被认为是重复提交,将不准许通过。
整个流程可以由如下流程来表述:
  1. 客户端申请token
  2. 服务器端生成token,并存放在session中,同时将token发送到客户端
  3. 客户端存储token,在请求提交时,同时发送token信息
  4. 服务器端统一拦截同一个用户的所有请求,验证当前请求是否需要被验证(不是所有请求都验证重复提交)
  5. 验证session中token是否和用户请求中的token一致,如果一致则放行
  6. session清除会话中的token,为下一次的token生成作准备
  7. 并发重复请求到来,验证token和请求token不一致,请求被拒绝
由以上的流程,我们整个实现需要以下几个东西
  1. token生成器,负责生成token
  2. 客户token请求处理action,负责处理客户请求,并返回token信息
  3. token拦截器,用于拦截指定的请求是否需要验证token
  4. token请求拦截标识,用于标识哪些请求是需要被拦截的
  5. 客户端token请求处理方法,用于请求token,并存放于特定操作中,并在提交时发送到请求中
token生成器
token生成器在这里使用了一个随机数来实现,即随机生成一个数字,即实现token生成,如下所示:
private static final Random random = new Random(System.currentTimeMillis());
public static final String TOKENPARAM = "session-token";

/** 生成一个token */
public static synchronized String generateToken(HttpSession session) {
String s = String.valueOf(random.nextLong());
session.setAttribute(TOKENPARAM, s);
return s;
}
token请求处理action
请求处理action,即接收相应的请求,然后直接返回相对应的token即可,如下即为一个为ajax请求生成token的处理action:
public String generateTokenAjax() {
String token = SessionTokenGenerator.generateToken(ServletActionContext.getRequest().getSession());
AjaxSupport.sendSuccessText(token);
return NONE;
}
token请求拦截标识
拦截标识,即表示哪些方法需要被拦截,这里可以使用注解来实现,即在要拦截的方法上追加类似@TokenNeed的注解,或者使用配置文件,将需要拦截的方法列表记录在配置文件中,在本文中,使用了一个配置文件来记录

token拦截器
token拦截器实现了我们所需要的拦截处理,在当碰到需要拦截的方法请求中,将同步进行token的判断和处理,并根据处理结果判断是否该继续放行或拦截之:

public String intercept(ActionInvocation invocation) throws Exception {
String action = invocation.getProxy().getAction().getClass().getName();
String method = invocation.getProxy().getMethod();
final HttpSession session = ServletActionContext.getRequest().getSession();
if(includeMethodSet.contains(action + "." + method)) {
synchronized(session) {
String paramSessionToken = ServletActionContext.getRequest().getParameter(SessionTokenGenerator.TOKENPARAM);
String sessionSessionToken = (String) session.getAttribute(SessionTokenGenerator.TOKENPARAM);
if(sessionSessionToken == null || paramSessionToken == null || !paramSessionToken.equals(sessionSessionToken))
return fail();
session.removeAttribute(SessionTokenGenerator.TOKENPARAM);
}
}
return invocation.invoke();
}
如上即是判断处理的方法是否在拦截列表中,如果是,则取得参数中的token,再将其与session中的token相比,如果不一致,则直接返回fail,随后将其从session中移除。

客户端token实现
作为客户端,只需要在进行请求提交之前申请一个token,在请求时,将此token加到请求中即可。在本文中,有一个jquery的ajax方法来处理token请求,随后在进行ajax请求时将此token一起加入到param。如下即为token的jquery请求
m_ylf.token = function() {
m_ylf.invoke("/token/generateToken",{}, function(re) {
re = re["result"];
window["session-token"] = re;
});
}
即在处理时将接收到的token放到window中,要提交请求时再将其从window中取出,一并提交即可,如下的统一ajax处理方法:

//追加session-token
if(window["session-token"])
param["session-token"] = window["session-token"];
至此,整个防session Token请求即完成
  • 14
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值