java 单用户登录
2018-04-02 本文已影响0人
_Rondo
一、概述
老项目做的app服务,提升用户体验,新加的单用户登录,注意是单用户不是单点,这里不涉及服务集群,有需求需要自己进行拓展,没用框架,是ejb3.0 servlet2.5,前后端分离;大体的逻辑为在过滤器中添加cookie登录验证,流程图如下:
单用户登录.jpg
二、代码示例
1.Filter
package com.mainsoft.online.sso;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.mainsoft.online.station.ServiceProxy;
import com.mainsoft.online.util.MyRequestWrapper;
/**
* 1.cookie存在, 非第一次登录,存在进行cookie登录,登录成功对比sessionid,不一致改写PWD库,一致放行
* 2.cookie不存在, 第一次登录,转发至ajaxservlet
* @author sxycw
*/
public class LoginFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//TODO 挖坑: 单系统soo,就是单用户,1.以后进行系统分布需要进行client与server拓展 2.安全性需要做sessionid持久性修改 和用户信息的加密
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//写出request 解决不能多次read的问题 转发时转发myRequestWrapper
MyRequestWrapper myRequestWrapper = new MyRequestWrapper(request);
String requestBody = myRequestWrapper.getBody();
JSONObject jsonLogin = JSONObject.parseObject(requestBody);
if(jsonLogin != null){
//剥离登录,不通过cookie login
if(jsonLogin.getString("method").equals("CheckLogin")
&& jsonLogin.getString("checkValue").equals("mainsoft")){
RequestDispatcher requestDispatcher = myRequestWrapper.getRequestDispatcher("/AjaxServlet.do");
requestDispatcher.forward(myRequestWrapper, response);
}else{
//cookie 登录验证,调试时取消控制台注释
Cookie cs[] = request.getCookies();
// System.out.println("-------app cookie 登录判定开始-------");
if (cs != null) {
// System.out.println("<<<<<获取传递cookie:"+JSON.toJSONString(cs));
//开始登录
Cookie c = cs[0];
// if( c.getMaxAge() > 0 ){//当前cookie未过期
if(c.getName().equals("userLoginCookie")){
// System.out.println("1.cookie 存在,开始进行参数拆分");
//对传递的cookie进行参数拆分 0 ==> username ; 1 ==> userpwd ; 2 ==> sessionid
String arr[] = c.getValue().split(",");
// System.out.println(JSON.toJSONString(arr));
//app 使用 cookie 登录
String result = ServiceProxy.indexservice.CheckLogin(arr[0], arr[1]);
// System.out.println("2.cookie 登录完成,开始验证登录结果");
JSONObject jobj = JSONObject.parseObject(result);
if(jobj.getString("Success") != null
&& jobj.getString("Success") != ""
&& jobj.getString("Success").equals("true")){
// System.out.println("3.验证完成,cookie 登录成功,开始对比是否同一浏览器");
//查询是否同一浏览器
String result1 = ServiceProxy.indexservice.getPWDSessionIDByCode(arr[0]);
if(result1 != null && result1 != ""){
// System.out.println(JSON.toJSONString(result1));
//验证结果
JSONObject jobj1 = JSONObject.parseObject(result1);
if(jobj1.getString("sessionid") != null){
if(!jobj1.getString("sessionid").equals(arr[2])){
//已另一台设备登录 销毁sesion
if (request.getSession().getAttribute("userLoginSession") != null) {
request.getSession().invalidate();
}
// System.out.println("4.不同浏览器,销毁cookie");
Cookie cookie = new Cookie("userLoginCookie",c.getValue());
cookie.setPath(myRequestWrapper.getContextPath());
cookie.setMaxAge(0);//销毁
response.addCookie(cookie);
// System.out.println("5.写返回信息,另一台设备已经登录");
renderDefaultJson(response,true);
}else{
// System.out.println("4.同一浏览器 放行");
//系统宕机或更新重启,cookie登录对比相同,放行
chain.doFilter(myRequestWrapper, response);
}
}
}
}else{
// System.out.println("3.cookie 登录失败");
renderDefaultJson(response,false);
}
// }
}else{
// System.out.println("cookie 过期");
renderDefaultJson(response,false);
}
// System.out.println("-------app cookie 登录判定结束-------");
}else{
//cookie 不存在 登录转发
RequestDispatcher requestDispatcher = myRequestWrapper.getRequestDispatcher("/AjaxServlet.do");
requestDispatcher.forward(myRequestWrapper, response);
}
}
}
}
@Override
public void init(FilterConfig config) throws ServletException {
}
/**
* cookie登录异常返回信息
* @author sxycw
*/
private void renderDefaultJson(HttpServletResponse response,boolean bool){
PrintWriter out;
try {
out = response.getWriter();
String jsonResult = null;
if(bool){
jsonResult = "{\"LoginDefault\":\"false\",\"Info\":\"您的账户已在另一设备登录,您已被迫下线!\"}";
}else{
//非写sessionid 都返回重新登录信息
jsonResult = "{\"LoginDefault\":\"false\",\"Info\":\"您的登录已过期,请重新登录!\"}";
}
out.println(jsonResult);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.需要用到的两个工具类,request读流和request存流
package com.mainsoft.online.util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* requestwrapepr
* @author sxycw
*
*/
public class MyRequestWrapper extends HttpServletRequestWrapper{
private String body;
/**
* 解决request流读一次丢失的问题
* @param request
*/
public MyRequestWrapper(HttpServletRequest request) {
super(request);
body = RequestUtil.getRequestBody(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
public String getBody(){
return body;
}
}
package com.mainsoft.online.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.http.HttpServletRequest;
/**
* request工具类
* @author sxycw
*
*/
public class RequestUtil {
/**
* get request io (json)
* @author sxycw
* @param request
* @return String
*/
public static String getRequestBody(HttpServletRequest request){
StringBuilder buffer = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(
new InputStreamReader(request.getInputStream(), "UTF-8"));
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != reader) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return buffer.toString();
}
}
3.最后添加过滤器到xml入口中
<!--配置过滤器-->
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.mainsoft.online.sso.LoginFilter</filter-class>
</filter>
<!--映射过滤器-->
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<!--“/*”表示拦截所有的请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
4.前台使用$.ajax中的dataFilter对参数进行预处理,接收到 logindefault就返回登录页
-end-