java同一浏览器session问题和QQ账号异地登陆案例
2017-08-21 11:09
706 查看
1.在JAVA WEB项目开发的过程中,我们常常会遇到这么一种情况,就是使用管理员账号登陆和用户账号同时在一个浏览器进行登陆的过程中,管理员账号和用户账号的session不会改变,这就是一个非常大的问题,那么这种问题应该怎么解决呢,这是我个人的解决方案,仅仅做参考
(1).在同一个浏览器同时登陆,这个时候无非就是session中的key一样这个时候我们只要保证账号中的session存储的过程中key不一样那么问题就迎刃而解,那么同样的,多个账号在同一浏览器同时登陆呢?那么这个时候自然就要去保证每一个账号的key都不一样,具体的这个怎么去实现,我们就得以一种什么样的方式去创建他,这里可以保存在Application作用域中,或者保存在内存中,或者在数据库中,这个就看个人的具体情况具体去设定
(2).同一个浏览器如果只是管理员和用户之间的问题,我们还可以去通过设置一个拦截器,在登陆的过程中我们先去判断是否有这个session如果有这个时候,再去获取这个访问的路径是否有这个权限,管理员的访问路径和用户之间的访问路径肯定都是不一样的,或者你的数据库中等肯定自然有什么去区分这个管理员和用户的,如果没有session,那么这个时候肯定就是先去获取这个路径看是否是登陆的路径,如果是就放行,不是就让他跳转到登陆界面.
(3).就是使用cookie机制,这种登陆一般都还是使用session,这个方案我个人不太推荐,使用cookie我们得注意一个问题,那就是cookie里面不能保存大量的客户信息,毕竟cookie是保存在客户端,信息不安全,还有就是cookie用户可以通过手动的去清除,还有就是可能会根据你cookie中的信息去分析,从而一些伪数据达到一种cookie欺骗
2.在项目的过程中我们常常还会遇到一个问题,那就是同一个账号不能够在两个浏览器同时登陆,这对很多的项目都是很有必要的,不管是从你的账号安全上考虑,还是说从你的业务需要上等这也是一个很棘手的问题,那么这是我在做一个项目过程中我个人的一个解决方案,仅仅提供参考
1.首先我定义一个工具类,里面有一个线程Map key就是用户Id,值就是用户,主要是负责管理用户上线,下线,踢出某用户,返回所有的在线用户,返回用户数量等这个一个工具类
2.我还有一个工具类就是用户去判断用户是否登陆,session是否失效,账号是否可用,以及账号异地登陆判断等
(1.)这里我先说一个知识点,那就是同一个浏览器在同义词登陆的过程中所产生的sessionId都是一样的,只有在这个浏览器sessionId关闭啦这个时候sessionId才会是一个新的,还有就是不同浏览器之间的sessionId都是不一样的
这样我们就可以通过这个去判断当前的sessionId是否发生变化,我们只要当前用户登陆的过程中我们就吧这个账号与当前的账号进行关联,可以通过一个map进行关联,也可以是与当前的用户bean关联等都可以,这样我们每次一登陆就可以在这个所有的在线用户里面去获取当前登陆的这个账号的sessionId都是发生了改变,这样我们就实现了这个功能,但是这里还有一个问题,那就session失效的问题,当session失效这个时候在线用户的那个工具类中的当前用户是需要进行删除的,以及当用户关闭浏览器的时候也是需要进行重新处理的这个就要看你的个人业务处理啦,重新的登陆,或者你用的是断点登陆,这个时候就不需要重新的登陆,看个人情况而定,这个时候我们是需要定义一个session监听器的,需要去监听session的创建,销毁等具体业务看你们的需求
这里我们其实还有不能仅仅的去靠自己的sessionId去判断,比如你的Ip地址(ip地址是可以改变的注意),以及根据你的用户某个唯一的区分字段等,都是可以实现的
说到这里这里自然就还还可以实现一个功能,那就在线用户统计功能
public class UserOnlineUtil {
/**
* 在线用户map
*/
private Map<Long, DataUser> userMap = Collections
.synchronizedMap(new LinkedHashMap<Long, DataUser>());
/**
* 上线
*
* @param user
*/
public void onLine(DataUser user) {
removeUser(user.getUserId());
userMap.put(user.getUserId(), user);
}
/**
* 下线
*
* @param user
*/
public void offLine(DataUser user) {
if (user.getLogout()<1) {
removeUser(user.getUserId());
}
}
/**
* 踢出某用户
*
* @param userId
*/
public void removeUser(long userId) {
DataUser user = (DataUser) userMap.remove(userId);
if (user != null) {
user.setLogout(1);
}
}
/**
* 返回在线用户数量
*
* @return
*/
public long getUserCount() {
return userMap.size();
}
/**
* 返回所有在线用户
*
* @return
*/
public DataUser[] getAllUser() {
return userMap.values().toArray(new DataUser[0]);
}
}
//部分代码
public String loginForm(){
String uname=ServletActionContext.getRequest().getParameter("uname");
String upwd=ServletActionContext.getRequest().getParameter("nloginpwd");
if(uname!=null&&upwd!=null){
DataUser user=userService.queryLogin(uname,upwd);
if(user!=null){
user.setSessionId(request.getSession().getId());
userOnlineUtil.onLine(user);
request.getSession().setAttribute(SessionManagerUtil.admin_Manager, user);
}
}
}
public class UserSessionLoseUtil {
private static Map<String,String> msgMap;
private UserOnlineUtil userOnlineUtil;
private Message msg;
public Message getSession(){
msg=new Message();
msgMap=new HashMap<String, String>();
HttpSession session=ServletActionContext.getRequest().getSession();
DataUser user=(DataUser) session.getAttribute(SessionManagerUtil.user_Manager);
DataUser u=isValidate(user);
if(user==null){//session 失效
msg.setCode("0");
msg.setFlag(false);
msg.setMsg(msgMap.get("0"));
return msg;
}else if(user.getState()==1){//账号不可用
msg.setCode("1");
msg.setFlag(false);
msg.setMsg(msgMap.get("1"));
return msg;
}else if(u==null||!u.getSessionId().equals(session.getId())){
msg.setCode("4");
msg.setFlag(false);
msg.setMsg(msgMap.get("4"));
return msg;
}else{
msg.setFlag(true);
msg.setUser(user);
return msg;
}
}
public DataUser isValidate(DataUser user){
ApplicationContext ctx= WebApplicationContextUtils.
getRequiredWebApplicationContext(ServletActionContext.getRequest().getSession().getServletContext());
UserOnlineUtil onlineUtil = (UserOnlineUtil) ctx.getBean("userOnlineUtil");
DataUser[] users=onlineUtil.getAllUser();
if(user!=null){
for(int i=0;i<users.length;i++){
if(users[i].getUserId()==user.getUserId()){
return users[i];
}
}
}
return null;
}
public Map<String, String> getMsgMap() {
return msgMap;
}
public void setMsgMap(Map<String, String> msgMap) {
this.msgM
abc9
ap = msgMap;
}
public Message getMsg() {
return msg;
}
public void setMsg(Message msg) {
this.msg = msg;
}
public UserOnlineUtil getUserOnlineUtil() {
return userOnlineUtil;
}
public void setUserOnlineUtil(UserOnlineUtil userOnlineUtil) {
this.userOnlineUtil = userOnlineUtil;
}
}
public class OnLineCount implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se) {
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
String sessionId=se.getSession().getId();
ApplicationContext ctx= WebApplicationContextUtils.
getRequiredWebApplicationContext(se.getSession().getServletContext());
UserOnlineUtil onlineUtil = (UserOnlineUtil) ctx.getBean("userOnlineUtil");
DataUser[] allUser = onlineUtil.getAllUser();
for (int i = 0; i < allUser.length; i++) {
if(sessionId.equals(allUser[i].getSessionId())){
onlineUtil.removeUser(allUser[i].getUserId());
}
}
}
}
监听器需要自己去web.xml配置 然后还有一些注入就就需要自己去写,以及你还有一些业务逻辑,这里都是一些关键性代码,具体的只能提供一个思路给你了
(1).在同一个浏览器同时登陆,这个时候无非就是session中的key一样这个时候我们只要保证账号中的session存储的过程中key不一样那么问题就迎刃而解,那么同样的,多个账号在同一浏览器同时登陆呢?那么这个时候自然就要去保证每一个账号的key都不一样,具体的这个怎么去实现,我们就得以一种什么样的方式去创建他,这里可以保存在Application作用域中,或者保存在内存中,或者在数据库中,这个就看个人的具体情况具体去设定
(2).同一个浏览器如果只是管理员和用户之间的问题,我们还可以去通过设置一个拦截器,在登陆的过程中我们先去判断是否有这个session如果有这个时候,再去获取这个访问的路径是否有这个权限,管理员的访问路径和用户之间的访问路径肯定都是不一样的,或者你的数据库中等肯定自然有什么去区分这个管理员和用户的,如果没有session,那么这个时候肯定就是先去获取这个路径看是否是登陆的路径,如果是就放行,不是就让他跳转到登陆界面.
(3).就是使用cookie机制,这种登陆一般都还是使用session,这个方案我个人不太推荐,使用cookie我们得注意一个问题,那就是cookie里面不能保存大量的客户信息,毕竟cookie是保存在客户端,信息不安全,还有就是cookie用户可以通过手动的去清除,还有就是可能会根据你cookie中的信息去分析,从而一些伪数据达到一种cookie欺骗
2.在项目的过程中我们常常还会遇到一个问题,那就是同一个账号不能够在两个浏览器同时登陆,这对很多的项目都是很有必要的,不管是从你的账号安全上考虑,还是说从你的业务需要上等这也是一个很棘手的问题,那么这是我在做一个项目过程中我个人的一个解决方案,仅仅提供参考
1.首先我定义一个工具类,里面有一个线程Map key就是用户Id,值就是用户,主要是负责管理用户上线,下线,踢出某用户,返回所有的在线用户,返回用户数量等这个一个工具类
2.我还有一个工具类就是用户去判断用户是否登陆,session是否失效,账号是否可用,以及账号异地登陆判断等
(1.)这里我先说一个知识点,那就是同一个浏览器在同义词登陆的过程中所产生的sessionId都是一样的,只有在这个浏览器sessionId关闭啦这个时候sessionId才会是一个新的,还有就是不同浏览器之间的sessionId都是不一样的
这样我们就可以通过这个去判断当前的sessionId是否发生变化,我们只要当前用户登陆的过程中我们就吧这个账号与当前的账号进行关联,可以通过一个map进行关联,也可以是与当前的用户bean关联等都可以,这样我们每次一登陆就可以在这个所有的在线用户里面去获取当前登陆的这个账号的sessionId都是发生了改变,这样我们就实现了这个功能,但是这里还有一个问题,那就session失效的问题,当session失效这个时候在线用户的那个工具类中的当前用户是需要进行删除的,以及当用户关闭浏览器的时候也是需要进行重新处理的这个就要看你的个人业务处理啦,重新的登陆,或者你用的是断点登陆,这个时候就不需要重新的登陆,看个人情况而定,这个时候我们是需要定义一个session监听器的,需要去监听session的创建,销毁等具体业务看你们的需求
这里我们其实还有不能仅仅的去靠自己的sessionId去判断,比如你的Ip地址(ip地址是可以改变的注意),以及根据你的用户某个唯一的区分字段等,都是可以实现的
说到这里这里自然就还还可以实现一个功能,那就在线用户统计功能
public class UserOnlineUtil {
/**
* 在线用户map
*/
private Map<Long, DataUser> userMap = Collections
.synchronizedMap(new LinkedHashMap<Long, DataUser>());
/**
* 上线
*
* @param user
*/
public void onLine(DataUser user) {
removeUser(user.getUserId());
userMap.put(user.getUserId(), user);
}
/**
* 下线
*
* @param user
*/
public void offLine(DataUser user) {
if (user.getLogout()<1) {
removeUser(user.getUserId());
}
}
/**
* 踢出某用户
*
* @param userId
*/
public void removeUser(long userId) {
DataUser user = (DataUser) userMap.remove(userId);
if (user != null) {
user.setLogout(1);
}
}
/**
* 返回在线用户数量
*
* @return
*/
public long getUserCount() {
return userMap.size();
}
/**
* 返回所有在线用户
*
* @return
*/
public DataUser[] getAllUser() {
return userMap.values().toArray(new DataUser[0]);
}
}
//部分代码
public String loginForm(){
String uname=ServletActionContext.getRequest().getParameter("uname");
String upwd=ServletActionContext.getRequest().getParameter("nloginpwd");
if(uname!=null&&upwd!=null){
DataUser user=userService.queryLogin(uname,upwd);
if(user!=null){
user.setSessionId(request.getSession().getId());
userOnlineUtil.onLine(user);
request.getSession().setAttribute(SessionManagerUtil.admin_Manager, user);
}
}
}
public class UserSessionLoseUtil {
private static Map<String,String> msgMap;
private UserOnlineUtil userOnlineUtil;
private Message msg;
public Message getSession(){
msg=new Message();
msgMap=new HashMap<String, String>();
HttpSession session=ServletActionContext.getRequest().getSession();
DataUser user=(DataUser) session.getAttribute(SessionManagerUtil.user_Manager);
DataUser u=isValidate(user);
if(user==null){//session 失效
msg.setCode("0");
msg.setFlag(false);
msg.setMsg(msgMap.get("0"));
return msg;
}else if(user.getState()==1){//账号不可用
msg.setCode("1");
msg.setFlag(false);
msg.setMsg(msgMap.get("1"));
return msg;
}else if(u==null||!u.getSessionId().equals(session.getId())){
msg.setCode("4");
msg.setFlag(false);
msg.setMsg(msgMap.get("4"));
return msg;
}else{
msg.setFlag(true);
msg.setUser(user);
return msg;
}
}
public DataUser isValidate(DataUser user){
ApplicationContext ctx= WebApplicationContextUtils.
getRequiredWebApplicationContext(ServletActionContext.getRequest().getSession().getServletContext());
UserOnlineUtil onlineUtil = (UserOnlineUtil) ctx.getBean("userOnlineUtil");
DataUser[] users=onlineUtil.getAllUser();
if(user!=null){
for(int i=0;i<users.length;i++){
if(users[i].getUserId()==user.getUserId()){
return users[i];
}
}
}
return null;
}
public Map<String, String> getMsgMap() {
return msgMap;
}
public void setMsgMap(Map<String, String> msgMap) {
this.msgM
abc9
ap = msgMap;
}
public Message getMsg() {
return msg;
}
public void setMsg(Message msg) {
this.msg = msg;
}
public UserOnlineUtil getUserOnlineUtil() {
return userOnlineUtil;
}
public void setUserOnlineUtil(UserOnlineUtil userOnlineUtil) {
this.userOnlineUtil = userOnlineUtil;
}
}
public class OnLineCount implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se) {
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
String sessionId=se.getSession().getId();
ApplicationContext ctx= WebApplicationContextUtils.
getRequiredWebApplicationContext(se.getSession().getServletContext());
UserOnlineUtil onlineUtil = (UserOnlineUtil) ctx.getBean("userOnlineUtil");
DataUser[] allUser = onlineUtil.getAllUser();
for (int i = 0; i < allUser.length; i++) {
if(sessionId.equals(allUser[i].getSessionId())){
onlineUtil.removeUser(allUser[i].getUserId());
}
}
}
}
监听器需要自己去web.xml配置 然后还有一些注入就就需要自己去写,以及你还有一些业务逻辑,这里都是一些关键性代码,具体的只能提供一个思路给你了
相关文章推荐
- Android(java)学习笔记212:中文乱码的问题处理(qq登录案例)
- session+application+cookie 实现单态登陆,且解决浏览器意外关闭的问题(转自http://blog.csdn.net/u010723709/article/details/4)
- javaWeb_session案例一:09-利用session完成用户登陆
- Java编写山寨QQ中遇到的各种问题---登陆界面
- 利用session+application+cookie 实现单态登陆,且解决浏览器意外关闭的问题
- Java+MySql+Servlet+Ajax实现单态登陆,说白了就是一个账号只能在一个浏览器中登陆。
- nokia的上网、彩 信设置以及QQ等JAVA程序不能上网的问题
- 一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)
- ArcGIS Server for the Java Platform中manager无法登陆的问题
- 解决ArcGIS Server for the Java Platform中manager无法登陆的问题
- 一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)
- Oracle10gR2中用浏览器登陆isql*plus dba页面问题小记
- 浏览器关闭时 清除服务端相应SESSION的问题
- Oracle10g中用浏览器登陆isql*plus dba页面问题
- 一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)(我还没有实验过)
- asp.net 退出登陆(解决退出后点击浏览器后退问题仍然可回到页面问题)
- 在小工具中维护状态(在一个浏览器里同时登陆两个账号同时进行操作的实现)
- JAVA Web 安全机制----使用filter验证session用户和页面缓存问题处理
- 在线人数统计,解决了关闭浏览器窗口,释放session的问题
- (转)一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)