这篇文章将为大家详细讲解有关J2EE下怎样模仿token机制,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
现在很多移动应用需要与后台交互,与后台交互就需要身份认证。最初想到用token的方式是当初看到微信公众平台的身份认证时采用了token这样的一个参数,然后自己也照着实现了一个。
说到这个token机制,一个是调用端,一个是后台。调用端我用JAVA语言开发的Android应用来展示,后台用J2EE来展示。
一、token的获取
token的获取其实就是移动端的登录过程,在登录的时候要先向后台获取一个token值,首先来看登录时Android端的代码:
String name = (EditText)mName.getText().toString(); String password = (EditText)mPsw.getText().toString(); String url2 = "http://"+ip+":"+port+"/test/be/login.do?method=login"; OkHttpClientManager ohm = OkHttpClientManager.getInstance(); OkHttpClientManager.Param[] params = new OkHttpClientManager.Param[]{ new OkHttpClientManager.Param("name", name), new OkHttpClientManager.Param("password", password)}; OkHttpClientManager.ResultCallback cb = new OkHttpClientManager.ResultCallback<String>() { @Override public void onError(Request request, Exception e) { String resultMsg = "请求失败,请检查网络连接!"; ToastUtil.showToastMsgError(LoginActivity.this, resultMsg); cancleAnimation();//关闭登录等待框 } @Override public void onResponse(String response) { JSONObject returnJson = JSONObject.parseObject(response); String resultId = returnJson.get("resultId").toString(); if (resultId.equals("00")) { token = returnJson.get("token").toString(); System.out.println("======================token:" + token); startApp();//进入应用 } else { token = ""; String resultMsg = returnJson.get("resultMsg").toString(); ToastUtil.showToastMsgError(NewLoginActivity.this, resultMsg); cancleAnimation(); } } }; OkHttpClientManager.getInstance().postAsyn(url2,cb, params);
OkHttpClientManager是经过封装的OkHttp的调用类,可以直接调用向后台发起http请求。
然后我们来看下后台的处理,这里后台有几个注意点:首先,login接口必须不被拦截器和过滤器给拦住,然后将用户名和密码传输到ctrl层,然后验证该用户名密码的真实有效性,如果合适身份,返回token,如果身份有问题,返回相应的提示信息。
@RequestMapping(params="method=login") @ResponseBody public String login(HttpServletRequest request,HttpServletResponse response,SysUser command) throws Exception{ String resStr = ""; try{ String name = command.getName(); String password = command.getPassword(); UserSession userSession=new UserSession(); // 设置usersession登录模式 userSession.setDlms("1"); command.setDlms("1"); SysUser sysuser=new SysUser(); Department department=new Department(); if(name==null||name.length()<1||name.indexOf("'")!=-1){ throw new Exception("该用户不存在!"); } if(password==null||password.length()<1||password.indexOf("'")!=-1){ throw new Exception("该密码不存在!"); } String strRemoteAddr=FuncUtil.getRemoteIpdz(request); // 获取ip地址 System.out.println("strRemoteAddr:"+strRemoteAddr); sysuserManager.validateSysuser(command,userSession,strRemoteAddr);//校验用户名、密码,有问题会直接throw异常 sysuser=this.sysuserManager.getSysuserByUsername(name);//获取用户信息 if(sysuser==null){ throw new Exception(Constants.SYS_NO_RIGHT); } sysuser.setIp(strRemoteAddr);// 设置登录人员的ip地址 sysuser.setDlms(command.getDlms()); department=this.departmentManager.getDepartment(sysuser.getGlbm()); if(department==null) throw new Exception(Constants.SYS_NO_HIGHXZQH); UUID token = UUID.randomUUID(); userSession.setSysuser(sysuser);//sysuser userSession.setDepartment(department); userSession.setYhdh(sysuser.getYhdh()); userSession.setGlbm(department.getGlbm()); userSession.setScdlsj(new Date().getTime()+""); RestfulSession.setSession(token.toString(), userSession); Map<String, Object> resultMap = new HashMap<String, Object>(); resultMap.put("resultId", "00"); resultMap.put("user", sysuser); resultMap.put("token", token.toString()); resStr = JSON.toJSONString(resultMap);//返回toekn和用户信息 }catch(Exception e){ Map<String, Object> resultMap = new HashMap<String, Object>(); resultMap.put("resultId", "01"); resultMap.put("resultMsg", e.getMessage()); resStr = JSON.toJSONString(resultMap);//返回异常 } return resStr; }
RestfulSession,这个类中的静态参数主要就是用来缓存正在登录中的用户的token与对应的session
package com.tmri.framework.bean; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import com.tmri.share.frm.bean.UserSession; public class RestfulSession{ private static Map<String,UserSession> session=new HashMap<String,UserSession>(10000);//最多放一万个用户信息 private static Map<String,String> clients=new HashMap<String,String>(); public static UserSession getSession(String sessionId){ return session.get(sessionId); } public static void setSession(String sessionId,UserSession clientUser){ String yhdh=clientUser.getYhdh(); String token=clients.get(yhdh); if(StringUtils.isNotEmpty(token)){ session.remove(token); } session.put(sessionId,clientUser); clients.put(clientUser.getYhdh(),sessionId); } public static void renewal(String sessionId){ session.get(sessionId).setScdlsj(new Date().getTime()+“”); } }
二、token的调用
登录后每次向后台的请求都要带上这个token值。如果移动端规定时间(暂时定义为半小时)内没有向后台发起请求,该token作废,后台返回token超时的提示。说到这里,明眼人也看出来了,其实这个机制也是模仿J2EE的session机制。
以下是Android端登录后向后台发起访问的代码,一定要带着token:
String creatUrl = "http://"+ip+":"+port+"/test/be/test.do?method=mytest"+"&token="+token; OkHttpClientManager.ResultCallback cb = new OkHttpClientManager.ResultCallback<String>() { @Override public void onError(Request request, Exception e) { ToastUtil.showToastMsgError(TestActivity.this, "回应服务器失败"); } @Override public void onResponse(String response) { JSONObject returnJson = JSONObject.parseObject(response); String resultId = returnJson.get("resultId").toString(); String resultMsg = ""; if(resultId.equals("00")){ resultMsg = "提交结果成功"; ToastUtil.showToastMsgError(TestActivity.this, resultMsg); } else if(resultId.equals("98")) // 会话过期 { relogin("当前连接已过期,是否重新登陆?"); }else{ //tasklist.clear(); resultMsg = "提交结果失败:"+returnJson.get("resultMsg").toString(); ToastUtil.showToastMsgError(TestActivity.this, resultMsg); } } }; OkHttpClientManager.getInstance().getAsyn(creatUrl,cb);
访问的时候除了加入白名单的url,其他请求都要经过拦截器的过滤,拦截器要判断这次的请求是移动端访问(带token的),还是一般的网页访问,有报错的话返回的东西也不一样,移动端访问报错的话返回的是定义好格式的json字符串,而网页访问的话返回的一般是报错页面(其实,如果web端用前端框架的话,也可以是定义好格式的json字符串)。
以下是后台的拦截器中的代码:
Long timeout = (long) 1800000;//超时时间,30min UserSession userSession; String token = request.getParameter("token"); if(StrUtil.checkBN(token)){ // 有token,接口访问 boolean flag=false; try{ userSession=RestfulSession.getSession(token); if(userSession!=null){ String currentURL=request.getServletPath(); if(!userSession.getMenuList().contains(currentURL+"?method="+request.getParameter("method"))){ sendRedirectJSON(request,response,"该用户没有权限"); return false; } Calendar now=Calendar.getInstance(); if(now.getTime().getTime()-Long.parseLong(userSession.getScdlsj())<timeout){// 如果该用户最后访问时间在30分钟以内 flag=true;// 允许访问 RestfulSession.renewal(token);//重置该次登录的session计时 }else{ sendRedirectJSON(request,response,"已超时"); return false; } } }catch(Exception e){ sendRedirectJSON(request,response,"请重新登录"); } if(!flag){ sendRedirectJSON(request,response,"未登录"); return false; }else{ return true; } }else{ //正常网页访问 userSession=(UserSession)request.getSession().getAttribute("userSession"); if(userSession==null){ sendRedirect(request,response); return false; } String url=""; if(StrUtil.checkBN(request.getParameter("method"))){ url=handler.getClass().getName().substring(handler.getClass().getName().lastIndexOf(".")+1,handler.getClass().getName().length())+"."+request.getParameter("method"); }else{ url=handler.getClass().getName().substring(handler.getClass().getName().lastIndexOf(".")+1,handler.getClass().getName().length()); } HashMap<String,String> rights=userSession.getRights(); if(rights==null){//没有权限 sendRedirect(request,response); return false; }else{ if(rights.containsKey(url)){ return true; }else{//没有权限 sendRedirect(request,response); return false; } } }
关于J2EE下怎样模仿token机制就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。