app基本都有用户注册登录相关的操作,那么登录后服务器需要做什么?当用户发起其他的请求时,怎么确定用户的唯一性,根据什么来把app用户和服务器关联起来?
之前问过一些新手,发现很多新手都是采用的如下方式:用户登录时,校验账号密码,如果正确的话,就给app返回一个用户表里对应该用户的UserId唯一标识,然后以后app的所以请求都带着这个UserId,这样去进行app和服务器的关联,通过UserId去做查询等相关的接口操作。进行操作时每次根据UserId去查询User,然后进行各项操作。但这样是对的吗?试想一下,如果是这样,通信关系靠的是一个UserId,那其实登录与否都不重要,只要知道id即可,任何的接口操作譬如获取所有订单啊、提现啊之类的靠这个id来维持。这肯定是有问题的,很多接口的操作在不登录的情况下是不能发起请求的,譬如一些紧要的订单信息,账号余额信息,付款请求等,但有一些接口是可以不登录就能访问的,譬如广告的banner,商品的展示等。如果靠UserId来进行关联,那怎么知道用户是否登录了呢,反正通过UserId就能进行所有的操作了。甚至有一些User表主键生成策略是int型递增,那这就更简单了,直接去猜个id,就能对用户进行所有的操作了,岂不很危险。
事实上,对服务器来说,登录操作是一个有特殊意义的操作,代表了一次会话。下面来回头看一下,http请求中的几个内置对象,page,request,session,application。这里用到的有request和session。request代表请求对象,session代表会话对象。request作用在一次请求的范围内,比如说你这次要干什么,要达到一个目的。你要传递一个东西就用request,只用一次。而session就是一次回话,它的销毁为session到期,默认30分钟,可以修改,还有关闭浏览器session也会销毁。session就可以理解为会话,好比你和一个人谈话,你们两个之间交流的信息可以多次交互。从这可以看出,app发起的每一次请求是一个request,你请求服务器,服务器给你回一次值。那么session就是用来做登录后这次会话的保存,一旦app登录了,那么在这次会话中这个用户就是有一个唯一的session_id的。这个是app用户和服务器交互的唯一标志,当退出登录,或者session过期后,这个用户和服务器的关联就停掉了。下次再登录,会再有一个新的session_id。
User表的唯一标识UserId是不应该暴露给app客户端的,关联应该是靠着session会话来进行。正确的操作应该是登录后,服务器保存这个session状态,在session里存入用户的唯一标志,然后把session_id返回给客户端,下次app带着session_id来进行请求。服务器对session进行校验,如果session还在,说明用户已经登录,如果不在,那说明已退出登录,或者session已经过期,这样就不至于暴露用户主键UserId,避免被刷接口。
下面来讲一下如何用struts来做这件事,struts自带拦截器interceptor,可以对某些请求进行拦截,某些不拦截。非常方便。
有些代码我就不贴完整的,那些配置我也不写了,就说一下大概的流程。
我们先来写一个拦截器,SessionInterceptor.java
package mobile.util.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.StrutsStatics; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; /** * 手机端校验是否登录的拦截器 * * @author wolf * */ public class SessionInterceptor implements Interceptor { private static final long serialVersionUID = -520686124206452492L; public void destroy() { } public void init() { } public String intercept(ActionInvocation invocation) throws Exception { ActionContext actionContext = invocation.getInvocationContext(); HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST); HttpServletResponse response = (HttpServletResponse) actionContext.get(StrutsStatics.HTTP_RESPONSE); HttpSession session = request.getSession(); // 获取sessionid String sessionId = session.getId(); response.addHeader("sessionId", sessionId); String actionName = invocation.getAction().toString(); // 不拦截以下action if (actionName.contains("LoginAction") || actionName.contains("registRequestCode") || actionName.contains("verifyCode")) { return invocation.invoke(); } // 没保存过用户session,说明没登录,或者session过期 if (session.getAttribute(sessionId) == null) { // 用户未登录,跳到没登录处理的action session.invalidate(); response.sendRedirect(request.getContextPath() + "/mobile/NoLoginAction.action"); return null; } return invocation.invoke(); } }
在这个拦截器里,intetcept方法,能够获取到所有通过这个拦截器拦截的请求,并且做相应的处理,先获取session对象,把sessionId放到response的header里,将来返回给app用。然后有一些请求是在不登录的情况下也能访问的,不拦截的,这里我通过判断请求名字来确定哪些不需要拦截,譬如登录、注册、发验证码之类的,就不需要做拦截。其他的需要拦截的,就在session里获取attribute,来看这个sessionId里存的对象是否为空,如果空了,说明没登录或已超时,就跳转到没登录的处理去。不为空的话就invoke放行。那些session里存什么东西就由大家自行决定。在什么时候在session里存信息呢,当然是在登录成功后了。
下面是LoginAction的一段代码,里面有一些是自己的逻辑,不适用于别的项目,所以就看看思想就好了
public String logout() { HttpServletRequest request = ServletActionContext.getRequest(); request.getSession().invalidate(); BaseData basedata = new BaseData(); basedata.setCode(1); PrintUtil.print(JsonUtil.toJsonString(basedata)); return null; } /** * 登录 * @return */ public String login() { OlderManReturnBean returnBean = new OlderManReturnBean(); List<TbOlderMan> olderMans = olderManService.queryByName(userName); if(olderMans.size() == 0) { //用户不存在 returnBean.setCode(-1); } else if(!olderMans.get(0).getLoginPwd().equals(MD5.toMD5(password))) { //密码错误 returnBean.setCode(-2); } else { //登录成功 returnBean.setCode(0); returnBean.setOlderMan(olderMans.get(0)); HttpServletRequest request = ServletActionContext.getRequest(); request.getSession().setAttribute(request.getSession().getId(), olderMans.get(0).getOlderManId()); request.getSession().setMaxInactiveInterval(20); } PrintUtil.print(JsonUtil.toJsonString(returnBean)); return null; }
登录成功后,在session里put进去值,key就是sessionId,value是用户的UserId。下次用户发请求时,带着sessionId来请求,我们就从session里getAttribute(sessionId),就能得到UserId了,如果得不到,说明已经不在登录状态了。通过拦截器来判断用户是否在登录状态,是否放行一些不需要登录就能访问的请求。
setMaxInactiveInterval方法是设置session超时时间,单位是秒,我这里设个20秒,方便测试session超时。可以通过浏览器来进行这个登录操作,登录成功后通过debug就能看到sessionId,然后随便输出个值。过20秒后,再试图访问一个其他的请求时,拦截器就会判断出该sessionId已经超时了,所以session去getAttribute时就会为空,然后就跳到没登录的action了。实际使用中请根据自己的需求来设置超时时间。
下面说一下struts.xml的配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="mobile" namespace="/mobile" extends="json-default"> <interceptors> <interceptor name="sessionInterceptor" class="mobile.util.interceptor.SessionInterceptor" /> <interceptor-stack name="defaultStack"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="sessionInterceptor" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="defaultStack" /> <action name="NoLoginAction" class="mobile.action.base.NoLoginAction" /> <!-- 登录、注册、修改密码 --> <action name="*LoginAction" class="mobile.action.LoginAction" method="{1}" /> <action name="*SmsAction" class="mobile.action.SmsAction" method="{1}" /> <action name="*OlderManAction" class="mobile.action.olderman.OlderManAction" method="{1}" /> <action name="*UrgentPersonAction" class="mobile.action.olderman.UrgentPersonAction" method="{1}" /> </package> </struts>
在这个package里,写明用的interceptor,将来所有这个namespace下的请求都会先走一遍拦截器,你可以通过写多个struts-*.xml,来区分不同的package,使用不同的拦截器,或者有的action不使用拦截器,这个就看自己的业务了。注意,struts是靠package来区分的,一个package下都会走这个拦截器。所以就有两种方式来决定是否拦截某些请求,一种就是在上面的拦截器代码里通过action的name来设置,还有就是通过有的package写拦截器,有的不写,或者两种方法同时使用来进行复杂的逻辑判断,拦截特定的请求。
以上就是app登录后,服务器端应该做的处理,和拦截器相关的处理。
http://blog.csdn.net/tianyaleixiaowu/article/details/50616939
相关推荐
基于Android开发的APP服务器...本文系统地介绍了基于Android平台的APP服务器端设计,讨论了服务器端的需求分析和设计、服务器交互原理和实现方法、Java编程语言、MYSQL数据库、Apache Tomcat和Struts2框架等关键技术。
在Struts2中,Action类扮演控制器的角色,处理用户的请求,并调用模型层进行业务逻辑处理。同时,Struts2通过配置文件(struts.xml)定义了请求和Action之间的映射,使得请求路由变得清晰易懂。 该示例可能包含以下...
该项目的核心是服务器端开发,采用了Struts 2框架,这是一个流行的Java Web应用框架,用于构建动态、数据驱动的Web应用。下面我们将深入探讨Struts 2框架及其在服务器端开发中的关键作用。 Struts 2是由Apache软件...
Struts2和ExtJS4是两个非常流行的Java Web开发框架,它们可以协同工作,提供功能丰富的用户界面和高效的服务器端处理。"struts2-extjs4.rar"这个压缩包文件包含了一个示例项目,演示了如何使用ExtJS4与Struts2进行...
例如,`REQUEST`表示处理标准的HTTP请求,而`FORWARD`则处理由服务器端转发的请求。 #### 2. ActionContextCleanUp过滤器 为了确保每次请求都能获取到干净的上下文环境,通常还需要配置`ActionContextCleanUp`过滤...
Struts2是一个强大的MVC(模型-视图-控制器)框架,它在Java Web开发中广泛应用,用于构建可维护性和可扩展性高的企业级应用程序。ExtJS(现称为Sencha Ext JS)则是一个富客户端JavaScript库,用于创建交互式、数据...
### 在Struts2与Spring2.5结合DWR2配置使用方法 #### 一、概述 本文档将详细介绍如何在Struts2与Spring2.5...通过以上步骤,我们可以轻松地在Struts2和Spring框架中集成DWR来简化Ajax开发,提高开发效率和用户体验。
- **模型**:模型包含业务逻辑和数据管理,它与数据库交互并处理用户请求。 - **控制器**:控制器接收用户的HTTP请求,调用相应的模型方法,并决定返回哪个视图。 ## 3. Struts与Web App的关系 Struts框架为开发者...
4. `struts2-json-plugin`包:该包支持JSON(JavaScript Object Notation)数据格式的处理,使得Struts2可以方便地与JSON API进行交互,这对于现代Web应用的前后端分离尤其有用。 5. `struts2-tiles-plugin`包:这...
Struts2提供了灵活的配置选项、强大的拦截器机制、内置的表单处理等功能,使得开发者能够快速构建出稳定、高效的Web应用。 ### 如何整合这些技术 #### 使用Google Plugin for Eclipse安装GWT和App Engine SDK ...
- **SSH框架**:SSH框架是指Struts2 + Spring + Hibernate这三种开源技术的组合。这是一种常用的Web应用程序开发框架,可以简化Web应用的开发流程。在Android与服务器交互时,可以通过SSH框架来实现前后端分离,提高...
Struts2框架提供Action类,通过注解配置路由请求,以及Result类型来决定如何返回响应。 3. **Hibernate**:Hibernate是一个对象关系映射(ORM)工具,简化了数据库操作。它允许开发者使用Java对象而不是SQL语句来...
车联网在线加油APP是一款结合了移动互联网与汽车服务的创新应用,它主要...开发者需要具备扎实的Android编程基础,熟悉地图API的调用,了解Web服务交互,以及一定的服务器端开发经验,才能成功构建这样一个综合性应用。
5. **服务器端设计**:服务器端运用SSH(Spring、Struts2、Hibernate)三大框架,对位置信息进行精确处理,并与Android客户端进行数据交互,共同实现位置和轨迹的共享。 6. **用户管理**:用户分为普通用户和管理员...
- **Validation Framework for Struts**:提供了表单验证功能,可以在客户端或服务器端对用户输入进行检查,确保数据的正确性。 总的来说,Struts通过规范化的开发流程和组件,极大地简化了Java Web应用的开发,...
还有Struts2 JSON Plugin,方便JSON数据的处理,以满足前后端分离的需求。 总的来说,Struts2是一个功能强大且灵活的框架,它提供了许多工具和特性来简化Java Web开发,让开发者能更专注于业务逻辑的实现。通过深入...
Java是一种广泛应用的面向对象的编程语言,尤其在企业级应用和服务器端开发中占有重要地位。在记账本APP的上下文中,Java可能被用来实现数据处理、用户认证、数据库交互等功能。 【描述】提到的“基于JAVA开发的...
总之,防止重复提交是Web应用开发中的重要一环,可以通过Struts2提供的 `<s:token>` 标签结合拦截器,或者结合客户端验证和服务器端状态管理等多种方式来实现。正确实施这些措施,可以有效避免数据的不一致性,提高...