JAVA SSM框架下+Redis 实现单点登录(手把手教,一步步都很详细),含源码

Redis的安装和引用参考上一篇:Redis下载链接

1:什么是单点登录?
答:单点登录的英文名叫做:Single Sign On(简称SSO)。
一般我们的模块都是在同一个系统下,同一个tomcat(如图,以商城为例)


image

后来为了维护和资源我们把一个系统拆成多个子系统。


image

而单点登录就是其中的一部分。
我们有多个系统,每个系统都要输入一次账号和密码的话就会变得很麻烦,这时候就需要单点登录,只要其中一个子系统登录的话,其他系统都能自动登录。最为熟悉的例子就是淘宝和天猫,如果你淘宝登录后,打开天猫就能自动登录无需再输入账号和密码。

2:实现单点登录的思路(整个页面的流程)

image

假设两个页面
用户A系统没登陆,B系统没登陆
这时用户在A登陆,A生成token令牌存入cookie,redis存入已经登录参数
然后用户打开B系统登录页面,B系统登录页面发送请求,后端通过cookie获取到用户在A系统登录的信息
判断获取到的信息没有错误进行自动登陆

3:Demo代码(两个页面的代码是一样的,路径什么的改改就行了)
简单的登陆jq,ajax请求
前端

<body background="jquery/loginbg.jpg">
<div>
<form  style="margin: auto; width:230px" class="form-signin"  >
<h2 class="form-signin-heading"><font color="white">SSO1用户登录</font></h2>
<!-- <label>账号:</label> -->
<input type="text" id="txtUsername" class="form-control" name="username" placeholder="请输入账号" /><br/>
<!-- <label>密码:</label> -->
<input type="password" id="txtPassword" class="form-control" name="password" placeholder="请输入密码" /><br/>
<!-- <input type="submit" value="提交" /> -->
 <a class="btn btn-primary btn-block" id="tijiao">提交</a><br>
<!-- <button class="btn btn-primary btn-block"  id="tijiao">提交</button><br> -->
  <button class="btn btn-primary btn-block"  >重置</button><br>
<!-- <input type="reset" value="重置" /> -->
<input type="button" class="btn btn-primary btn-block" value="注册" onclick="window.location.href='add.jsp';"/>
</div>
<div id="chartmain" style="width:600px; height: 400px;  margin: auto; " class="form-signin"></div>
 
</body>
<script type="text/javascript">
    $("#tijiao").click(function(){
        var paramMap = {};
        paramMap.username = $("#txtUsername").val();
        paramMap.userpasswd = $("#txtPassword").val();
        $.ajax({
            type:'POST',
            data:JSON.stringify(paramMap),
            dataType:'JSON',
            url:"user/slogin",
            contentType :"application/json;charset=UTF-8",
            async: true,
            error:function(jqXHR){
                 alert("发生错误:"+ jqXHR.status); 
                },
             success:function(data){
                 if(data){
                    if(data.state == "success"){
                        window.location.href ='index.jsp';
                    }else if(data.state == "fault"){
                        window.location.href ='login.jsp';
                    } 
                 }
                  
                 }
        });
    })
    window.onload = function(){
        var paramMap = {};
        var i = 0;
        paramMap.username = $("#txtUsername").val();
        paramMap.userpasswd = $("#txtPassword").val();
        $.ajax({
            type:'POST',
            data:JSON.stringify(paramMap),
            dataType:'JSON',
            url:"user/slogin",
//          xhrFields: {
//              withCredentials: true // 携带跨域cookie
//          },
            contentType :"application/json;charset=UTF-8",
            async: true,
            error:function(jqXHR){
                 alert("发生错误:"+ jqXHR.status); 
                },
             success:function(data){
                 if(data){
                    if(data.state == "success"){
                        window.location.href ='index.jsp';
                    }else if(data.state == "fault"){
                        debugger;
                        var str=location.href; //取得整个地址栏
                        var num=str.indexOf("=") 
                        str=str.substr(num+1);
                        if(str!="1"||str==null){
                            window.location.href ='login.jsp?state=1';
                        }
                        
                    } 
                 }
                  
                 }
        });
}
    
    
    
    
</script>

后端

    /**
     * 登陆
     * @param <Account>
     * @param model
     * @param session
     * @return
     * @throws Exception 
     */
    @ResponseBody
    @RequestMapping(value = "/slogin", method = RequestMethod.POST)
    public ResultInfo slogin(@RequestBody Map<String, String> param,
            HttpSession session, HttpServletRequest request,
            ServletResponse response, HttpServletResponse responses)
            throws Exception {
        ResultInfo resultinfo = new ResultInfo();
        
        /**
         * 判断redis是否连接成功
         */
        //连接本地的 Redis 服务
        @SuppressWarnings("resource")
        Jedis jedis = new Jedis("localhost");
        System.out.println("连接成功");
        //用户验证
        String username = param.get("username");
        String passwd = param.get("userpasswd");
        
        if(jedis.exists("islogin")){
            //判断是否已经登录
            if(!jedis.get("islogin").equals("1")){
                // TODO: handle exception
                resultinfo.setState(StateType.fault);
                jedis.set("islogin", "0");
            }
        }else if(!jedis.exists("islogin") && username.length()==0 && passwd.length()==0){
            resultinfo.setState(StateType.fault);
            return resultinfo;
        }
        
        /**
         * 从cookie中获取数据
         */
        Cookie[] cookies = request.getCookies();
        System.out.println(cookies);
        String cookievalue = null;
        for(Cookie cookiexs : cookies){
            if(cookiexs.getName().equals("token")){
                cookievalue = cookiexs.getValue();
                break;
            }
        }
        
        if(cookievalue!=null){
            //base64解密
            String decusername = null;
            String decpasswd = null;
            int a = 1;
            byte[] decoded = Base64Utils.decode(cookievalue.getBytes());
            String decodeStr = new String(decoded,"UTF-8");
            System.out.println("Base 64 解密后:" + decodeStr);
            //获取用户名和密码
            for(int i=-1; i<=decodeStr.lastIndexOf("=");++i){
            i=decodeStr.indexOf("=",i);
            System.out.print(i+"\t");
            if(a==1){
                decusername = decodeStr.substring(i, i);
                a++;
            }else if(a>1){
                decusername = decodeStr.substring(5,i-6);
                decpasswd = decodeStr.substring(i+1, decodeStr.length()-6);
                a=1;
            }
             System.out.println("账号为:"+decusername+"\t"+"密码为:"+decpasswd);
             
            }
            username = decusername;
            passwd = decpasswd;
        }
        
        
        try {
            if(username  != "" && passwd !=""){
                User user = userService.loginUsername(username);
                if(user ==null){
                    resultinfo.setState(StateType.fault);
                    jedis.set("islogin", "0");
                    return resultinfo;
                }else if(!user.getPassword().equals(passwd)){
                    resultinfo.setState(StateType.fault);
                    jedis.set("islogin", "0");
                    return resultinfo;
                }
                //设置token
                String token = tokenset(user);
                
                //将数据保存到cookie中
                Cookie cookie = new Cookie("token", token);
                //cookie.setMaxAge(600);
                responses.addCookie(cookie);
                
                //将token发送给客户端,附带本次全局会话的sessionId
                //String allSessionId=request.getSession().getId();
                
                //获取sessionid
                String sessionid = session.getId();
                
                //设置状态(通过session判断该浏览器与认证中心的全局会话是否已经建立),生成令牌
                //判断用户是否登录
                request.getSession().setAttribute("isLogin", username);
                Map<String, String> tosession = new HashMap<String, String>();
                tosession.put("sessionid", sessionid);
                jedis.set("islogin", "1");
                jedis.set(token,username+passwd);
                jedis.expire("islogin", 120);
//              jedis.expire("token", 600);
                resultinfo.setData(token);
                resultinfo.setState(StateType.success);
            }
             if(jedis.get("islogin").equals("1")){
                 resultinfo.setState(StateType.success);
             }else{
                 resultinfo.setState(StateType.fault);
             }
            
            
        } catch (Exception e) {
            // TODO: handle exception
            resultinfo.setState(StateType.fault);
            resultinfo.setData(e.toString());
        }
        return resultinfo;
            
        
        
    }
/**
     * 设置token
     */
    private String tokenset(User user) {
        // TODO Auto-generated method stub
        String token = null;
        String sign = "hitomi";
        String param = "name="+user.getUsername()+"passwd="+user.getPassword()+sign;
        token = Base64Utils.encodeToString(param.getBytes());
        return token;
        
    }

此代码只是简单的实现单点登录的思路和功能,仅供参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

推荐阅读更多精彩内容