Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 528|回复: 0

安卓登录以及会话保持的解决方案

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-30 14:53:14 | 显示全部楼层 |阅读模式

    项目做到一半技术经理辞职了,留个烂摊子。web基本已做完,安卓的app要新写,项目开发完做个总结,这东西已经是好久前做的了。

    登录接口很快就写好了,登录成功后用户信息是缓存再session当中的

     /**
         * 用户登录
         *
         * @param user
         * @return
         */
        @RequestMapping(value = "doLogin")
        @ResponseBody
        public Map doLogin(User user, HttpServletRequest request) {
            Map result = Maps.newHashMap();
            try {
                LoginResult flag = FrontUserUtils.doLogin(user, request);
                if (flag == LoginResult.登录成功) {
    
                    Map<String, Object> map = new HashMap<>();
                    String[] propertys = new String[]{"name", "photo", "singleId"};
                    for (String property : propertys) {
                        map.put(property, Reflections.invokeGetter(FrontUserUtils.getUserBySession(), property));
                    }
                    result.put("flag", 1);
                    result.put("user", map);
                    return result;
                } else if (flag == LoginResult.用户被锁定) {
                    result.put("flag", 0);
                    result.put("msg", "用户被锁定,请联系管理员!");
                    return result;
                } else if (flag == LoginResult.登录失败) {
                    result.put("flag", 0);
                    result.put("msg", "账号或密码错误!");
                    return result;
                }
            } catch (Exception e) {
                result.put("flag", 0);
                result.put("msg", "操作失败!");
                e.printStackTrace();
            }
            return result;
        }
     /

     

    但是登录成功后,再调用其他需要获取登录用户信息的时候的时候发现在session中没有,不对啊,明明自已用浏览器测试是OK的啊,我自己补不了解嘛,

    技术经理也跑了,不知道怎么回事啊、咋整,我去问安卓,他也不懂啊,我也走吧。

     

    然后debug测试吧,用浏览器不这样啊,session是同一个呐。测试一下,在后台打印一下sessionid:

    浏览器访问接口:

    模拟安卓访问接口:

    每次都生成了新的session,这么搞不行啊,每次请求都生成新session,我怎么缓存你登录用户的信息啊。

     

    然后就想办法解决啊 ,想来想去想了两个方案

    方案1:自定义身份识别方式(token),类似自己模拟session

      再用户登录以后,在系统内生成一个唯一的身份标识,并将此标识返回给客户端。身份标识保存15天,如果用户,在其他终端登录,或者15天超时在服务器没有业务,将通知终端会话超时,重新登录。

     

      后台代码就不贴了,使用的uuid生成的一个字符串,作为用户的登录标识,将用户信息写入缓存,类似key :user这种方式存储。

     

             用户请求其他接口的时候,会被我的一个拦截器拦截,如果发现根据字符串查询用户查询不到,就会将用户剔除系统。

    拦截器:

    public class LoginInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            User user = FrontUserUtils.getUser();
            if (user == null || user.getId() == null || user.getId().equals("")) {
                returnJson(httpServletResponse);
                return false;
            } else {
                return true;
            }
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            e.notifyAll();
        }
    
    
        private void returnJson(HttpServletResponse response) throws Exception {
            PrintWriter writer = null;
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html; charset=utf-8");
            try {
                Map map = new HashMap();
                map.put("flag", 0);
                map.put("msg", "登陆会话已经过期,请重新登陆!");
                JSONObject jsonObject = JSONObject.fromObject(map);
                writer = response.getWriter();
                writer.print(jsonObject);
            } catch (IOException e) {
    
            } finally {
                if (writer != null)
                    writer.close();
            }
        }
    }

    这样写,牺牲掉了一部分系统性能,来实现安卓与服务器之间的长连接,因为基本拦截了所有的接口,每次都判断是否登录,或者登录超时。

     

     

     

    方案2:还是使用sessionId,其实两种方式都差不多,不过我还是推荐这种,第一种的花同一时间用户太多,session过多,可能导致其他的问题。

     

    web浏览器保持会话,是因为有session的存在,不同的服务器在浏览器请求的时候会判断是否为第一次请求,如果是第一次就回返回一个参数Set-Cookie,一般浏览器支持自己保存这个数据,这个数据也是浏览器与服务器保持会话的标识;

    比如以百度为例:

    再次请求相同的服务器,浏览器会从cookie中取出这些这值,加载到浏览器的请求中去

     

    浏览器如果不禁用cookie的话,浏览器就会将服务器返回的数据保存到cookie当中去,session与cookie不清楚的,去查资料吧。

     

     安卓的访问方式

    尽管安卓可以使用许多网络框架来进行访问,但是我不是很了解呐,加上公司的安卓开发也不甚了解,

     

    我觉得他是使用httpclient类似的方式来进行访问的,我就谢了一个代码模拟了下安卓的请求,来获取下服务器返回的数据,看能不能获取到 Set-Cookie;

     

    public class MainActivity {
    
        public static final String login_url="http://192.168.0.112:8080/login/doLogin?loginName=18866601116&password=123456zxc";
    
        /**
         * 安卓登录测试
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception {
    
            URL url=new URL(login_url);
            HttpURLConnection con=(HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            String cookieString=con.getHeaderField("Set-Cookie");
            System.out.print(cookieString);
    
        }
    }
    //控制台输出

     

     
    

      哎可以的。就让安卓再第一次请求服务器的时候将这个sessionid保存下来吧,缓存到手机,

    然后请求后台的时候,将保存的cookie放在httpPost的请求当中,这样访问服务器时,服务器就会认为是同一个用户了。也就是说保持了这个会话。

     

     

     

    其实两种方式的原理都差不多,如果有更好的方案,也可以跟我说,学习嘛。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-12 10:51 , Processed in 0.060752 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表