单点登录

HttpUtil

public class HttpUtil {
    /**
     * 模拟浏览器的请求
     * @param httpURL 发送请求的地址
     * @param params  请求参数
     * @return
     * @throws Exception
     */
    public static String sendHttpRequest(String httpURL,Map<String,String> params) throws Exception{
        //建立URL连接对象
        URL url = new URL(httpURL);
        //创建连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求的方式(需要是大写的)
        conn.setRequestMethod("POST");
        //设置需要响应结果
        conn.setDoOutput(true);
        //判断是否有参数.
        if(params!=null&&params.size()>0){
            StringBuilder sb = new StringBuilder();
            for(Entry<String,String> entry:params.entrySet()){
                sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
            }
            //sb.substring(1)去除最前面的&
            conn.getOutputStream().write(sb.substring(1).toString().getBytes("utf-8"));
        }
        //发送请求到服务器
        conn.connect();
        //获取远程响应的内容.
        String responseContent = StreamUtils.copyToString(conn.getInputStream(),Charset.forName("utf-8"));
        conn.disconnect();
        return responseContent;
    }
    /**
     * 模拟浏览器的请求
     * @param httpURL 发送请求的地址
     * @param jesssionId 会话Id
     * @return
     * @throws Exception
     */
    public static void sendHttpRequest(String httpURL,String jesssionId) throws Exception{
        //建立URL连接对象
        URL url = new URL(httpURL);
        //创建连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求的方式(需要是大写的)
        conn.setRequestMethod("POST");
        //设置需要响应结果
        conn.setDoOutput(true);
        conn.addRequestProperty("Cookie","JSESSIONID="+jesssionId);
        //发送请求到服务器
        conn.connect();
        conn.getInputStream();
        conn.disconnect();
    }
}

SSOClientUtil

public class SSOClientUtil {
    //统一认证中心地址(域名)
    public static final String SERVER_DOMAIN="http://www.sso.com";
    //统一认证中心检查是否已经登录的访问地址
    public static final String SERVER_CHECK_URL="/checkLogin?redirectUrl=";
    //统一认证中心的token认证地址
    public static final String SERVER_VERIFY_URL="/verify";
    //统一认证中心的登出地址
    public static final String SERVER_LOGOUT_URL="/logOut";
    //客户端的登出地址
    public static final String CLIENT_LOGOUT_URL="/logOut";
    //统一认证中心的token认证方法的token参数名
    public static final String TOKEN_NAME="token";
    //统一认证中心的token认证方法的登出地址参数名
    public static final String CLIENTURL="clientURL";
    //统一认证中心的token认证方法的jsessionid参数名
    public static final String JSESSIONID="jsessionid";
    /**
     * 获取客户端的完整登出地址 http://www.client1.com:8081/logOut
     * @return
     */
    public static String getClientLogOutUrl(HttpServletRequest request){
        //获取请求使用的协议,是http或者https
        String scheme = request.getScheme();
        //获取主机的名字 www.client1.com
        String serverName = request.getServerName();
        //获取请求的端口号 8081
        int serverPort = request.getServerPort();
        //获取请求URL
        String servletPath = request.getServletPath();
        String url = scheme+"://"+serverName+":"+serverPort+CLIENT_LOGOUT_URL;
        return url;
    }
    /**
     * 获取认证中心的登出地址 http://www.sso.com/logOut
     * @return
     */
    public static String getServerLogOutUrl(){
        String serverURL = SERVER_DOMAIN;
        String logOutURL = SERVER_LOGOUT_URL;
        return serverURL+logOutURL;
    }
    /**
     * 当客户端请求被拦截,跳往统一认证中心,需要带redirectUrl的参数,统一认证中心登录后回调的地址
     * 通过Request获取这次请求的地址 http://www.client1.com:8081/main
     * 
     * @param request
     * @return
     */
    public static String getRedirectUrl(HttpServletRequest request){
        //获取请求使用的协议,是http或者https
        String scheme = request.getScheme();
        //获取主机的名字 www.client1.com
        String serverName = request.getServerName();
        //获取请求的端口号 8081
        int serverPort = request.getServerPort();
        //获取请求URL
        String servletPath = request.getServletPath();
        String url = scheme+"://"+serverName+":"+serverPort+servletPath;
        return url;
    }
    /**
     * 根据request获取跳转到统一认证中心的地址 http://www.sso.com//checkLogin?redirectUrl=http://www.client1.com:8081/main
     * 通过Response跳转到指定的地址
     * @param request
     * @param response
     * @throws IOException
     */
    public static void redirectToSSOURL(HttpServletRequest request,HttpServletResponse response) throws IOException{
        String serverURL = SERVER_DOMAIN;
        String checkURL = SERVER_CHECK_URL;
        String redirectUrl = getRedirectUrl(request);
        StringBuilder url = new StringBuilder(50);
        url.append(serverURL).append(checkURL).append(redirectUrl);
        response.sendRedirect(url.toString());
    }
    /**
     * 验证token是否有效,如果有效把客户端的登出地址和jsessionid传递到统一认证中心,方便进行单点注销.
     * @param token 
     * @param clientURL
     * @param jsessionid
     * @return 
     */
    public static Boolean verify(String token, String clientURL,String jsessionid) {
        String serverURL = SERVER_DOMAIN;
        String verifyURL = SERVER_VERIFY_URL;
        Map<String,String> params = new HashMap<String,String>();
        params.put(TOKEN_NAME, token);
        params.put(CLIENTURL, clientURL);
        params.put(JSESSIONID, jsessionid);
        try {
            String responseContent = HttpUtil.sendHttpRequest(serverURL+verifyURL, params);
            if("true".endsWith(responseContent)){
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }
}

LoginFilter

public class LoginFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;

        //判断局部会话,看是否有登陆状态
        Object isLogin = request.getSession().getAttribute("isLogin");

        if(isLogin!=null&&(Boolean)isLogin){
            //直接放行
            chain.doFilter(request, response);
            return;
        }

        //判断参数是否有token
        Object token = request.getParameter("token");
        if(token!=null&&StringUtils.isNoneEmpty((String)token)){
            //如果有则进行校验
            boolean result = SSOClientUtil.verify((String)token,
                    SSOClientUtil.getClientLogOutUrl(request), request.getSession().getId());
            if(result){
                //创建局部会话
                request.getSession().setAttribute("isLogin",true);
                //直接放行
                //chain.doFilter(request, response);
                response.sendRedirect("/main");
                return;
            }
        }

        //跳转到认证中心进行验证(看是否有其他系统登陆过)
        //www.server.com/checkLogin
        //通过http请求来访问认证中心
        SSOClientUtil.redirectToSSOURL(request, response);


    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}

SSO Login

@Controller
public class LoginContrller {

    @RequestMapping("/checkLogin")
    public String checkLogin(String redirectUrl, Model model,HttpSession session){
        //如果已经登陆了(有其他客户端登陆过),就返回令牌给客户端
        Object token = session.getAttribute("token");
        if(token!=null){
              //代表已经登陆
              //就返回令牌给客户端
            model.addAttribute("token",token);
            return "redirect:"+redirectUrl;
        }
        model.addAttribute("redirectUrl",redirectUrl);
        return "login";
    }


    @RequestMapping("/login")
    public String login(String username, String password, String redirectUrl, Model model, HttpSession session){
        //做账号密码验证,如果验证成功需要重定向到客户端
        if("zhangsan".equals(username)&&"666".equals(password)){
            //创建令牌
            String token = UUID.randomUUID().toString();
            //创建全局会话
            session.setAttribute("token",token);
            //放入map中(只要存在map中的token都是合法的)
            SSOServerUtil.map.put(token,new ArrayList<String[]>());
            //把令牌传给客户端
            model.addAttribute("token",token);
            return "redirect:"+redirectUrl;
        }

        model.addAttribute("errorMsg","账号或密码错误!");
        model.addAttribute("redirectUrl",redirectUrl);
        return "login";
    }

    @RequestMapping("/verify")
    @ResponseBody
    public String verify(String token,String clientURL,String jsessionid){
        //验证token是否合法
        ArrayList<String[]> list = SSOServerUtil.map.get(token);
        if(list!=null){
            //合法(注册系统)
            list.add(new String[]{clientURL,jsessionid});
            return "true";
        }
        //不合法
        return "false";
    }

    @RequestMapping("/logOut")
    public String logOut(HttpSession session) throws Exception {
        //注销全局会话
        session.invalidate();
        return "login";
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值