sso(单点登录)_java原理版

sso(单点登录)
什么是sso?对比方式,以新浪为例
java语言的运行特点:平台无关,
sso:一次登录,处处穿梭,类似于一卡通.
sso的分类:
根据域的不同分为两类:
同域的sso
跨域的sso(如新浪微博和新浪博客)

sso的实现步骤和实现原理
旅游:通票制度
旅游,达到景区售票处,购买通票,到达某景点门口,是否持有通票?有,工作人员检验通过;否,达到景区售票处;通票是否有效?有
进入景点游览之后重复以上步骤至游览结束;否,达到景区售票处.
sso,打开统一登录页面,登录,同时服务器写入cookie,穿梭至某应用,是都有对应的cookie,有服务器验证cookie有效性,cookie是否有效?有,进入应用页面,穿梭至其他应用时,重复以上步骤,至浏览结束.否,打开统一登录界面,cookie是否有效?无,打开统一登录界面.关键点:cookie中的数据:是否有对应的cookie和cookie是否有效?无,返回统一登录页面.

需要登录一次,写入到cookie,验证cookie.
存储票据(登录页面,写入到cookie),和检查票据(是否有票是否有效).

3.同域的sso
http://localhost/demo1/main.action
http://localhost/demo2/main.action

同父域的sso
http://demo1.x.com/demo1/main.action
http://demo2.x.com/demo2/main.action
统一校验接口
http://check.x.com/sso/checkCookie.action
不在同一个域名里面,他们之间是需要服务之间的通信的.

修改host文件:(c:/Windows/System32/drivers/etc)
127.0.0.1  demo1.x.com
127.0.0.1  demo2.x.com
127.0.0.1  check.x.com

ssh开发环境
工具类
tomca的配置7.0.57
server.xml中
<Context path="" debug="0" docBase="项目绝对路径的根目录(d:\SSO_same_domain\WebRoot)") reloadable="false"/>
SSO_same_domain


编写统一登录接口
登录页面,处理程序共同构成
login.jsp
<body>
    <center>
        <h1>请登录</h1>
        <form action="/sso/doLogin.action" method="POST">
        <span>用户名:</span> <input type="text" name="username" />
        <span>密码:</span> <input type="password" name="password" />
        <input type="hidden" name="gotoUrl" value="${gotoUrl}" />
        <!-- 够买票后,要跳转的去向,先暂存起来,以后再做连接 -->
        <input type="submit">
    </center>
</body>

SSOAction.java
SSOAction extends ActionSupport

    username,password,gotoUrl  getter/setter
    String doLogin(){
        boolean ok = SSOCheck.checkLogin(username,password);
        if(ok){
            Cookie cookie = new Cookie("ssocookie","sso");
            cookie.setPath("/");
            HttpServerletResponse response = ServletActionContext.getResponse();
            response.addCookie(cookie);//这样就把cookie加入到了访问者的浏览器中
            return SUCCESS;
        }
        return null;
    }
SSOCheck.java
    static final String USERNAME="user";
    static final Stirng PASSWROD="123";
    boolean checkLogin(Stirng username,String password){
        if(username.equals(USERNAME)) && password.equals(PASSWROD))
            return true;
        return false;
    }

struts.xml
<struts>
    <package name="sso" namespace="/sso" extends="struts-default">
        <action name="doLogin" class="com.imooc.sso.SSOAction" method="doLogin">
            <result name="success" type="redirect">${gotoUrl}</result>
            <!-- 需要记录返回去的位置才是比较理想的 -->
        </action>
    </package>
    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="com.imooc.demo1.Demo1Action" method="main">
            <result name="success">/success1.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="com.imooc.demo2.Demo2Action" method="main">
            <result name="success">/success2.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
</struts>


4.编写登录校验接口
登录发生之前应该校验,是否持有合法的cookie
static boolen checkCookie(HttpServletRequest request){
    Cookie[] cookies = request.getCookie();
    if(cookie!=null){
        for(Cookie cookie:cookies){
            if(cookie.getName().equals("ssocookie") && cookie.getValue().equals("sso")){
                return true;
            }
        }
    }
    return false;
}
正确的cookie校验应该放在拦截器中校验的,如果校验到没有cookie或者cookie无效就跳转到登录页面,如果校验的cookie有效就跳转到主页.

demo1/main  success1.jsp  "欢迎访问demo1的主页"
demo2/main  success2.jsp  "欢迎访问demo1的主页"
com.imooc.demo1
com.imooc.demo2

Demo1Action extends ActionSupport{
    String gotoUrl; getter/setter
    String main(){
        HttpServletRequest request = ServletActionContext.getRequest();
        if(SSOCheck.checkCookie(request)){
            return SUCCESS;
        }
        gotoUrl ="/demo1/main.action";
        return LOGIN;
    }
}

Demo1Action extends ActionSupport{
    String gotoUrl; getter/setter
    String main(){
        HttpServletRequest request = ServletActionContext.getRequest();
        if(SSOCheck.checkCookie(request)){
            return SUCCESS;
        }
        gotoUrl ="/demo2/main.action";
        return LOGIN;
    }
}







同父域的sso
http://demo1.x.com/demo1/main.action
http://demo2.x.com/demo2/main.action
统一校验接口
http://check.x.com/sso/checkCookie.action
不在同一个域名里面,他们之间是需要服务之间的通信的.

修改host文件:(c:/Windows/System32/drivers/etc)
127.0.0.1  demo1.x.com
127.0.0.1  demo2.x.com
127.0.0.1  check.x.com

login.jsp(copy)
编写统一登录接口
登录页面,处理程序共同构成
login.jsp
<body>
    <center>
        <h1>请登录</h1>
        <form action="http://check.x.com/sso/doLogin.action" method="POST">
        <span>用户名:</span> <input type="text" name="username" />
        <span>密码:</span> <input type="password" name="password" />
        <input type="hidden" name="gotoUrl" value="${gotoUrl}" />
        <!-- 够买票后,要跳转的去向,先暂存起来,以后再做连接 -->
        <input type="submit">
    </center>
</body>

以三个包模拟三个服务器:
com.x.demo1
com.x.demo2
com.x.check

public class SSOAction extends ActionSupport{

    private String username;
    private String password;
    private String gotourl;

    public String dologin(){
        //同域下的sso
        boolean ok = SSOCheck.checklogin(username, password);
        if(ok){
            Cookie cookie = new Cookie("ssocookie", "sso");
            cookie.setDomain(".x.com");//x是父域名,放到这个父域下的最顶层
            cookie.setPath("/");//设置到顶层
            //cookie的路径设置问题,如果不设置cookie路径,那cookie的路径并不一定在当前域名路径的顶层.有可能就在当前的路径下才可见
            //这样会导致在当前域的其他路径下找不到cookie,解决办法就是把cookie设置到当前域的最顶层,这样就能保证当前域下所有的应用
            //对cookie都可见.是实现同父域sso的关键.
            HttpServletResponse response = ServletActionContext.getResponse();
            response.addCookie(cookie);
            return SUCCESS;
        }
        return "login";
    }


struts.xml
<struts>
    <package name="sso" namespace="/sso" extends="struts-default">
        <action name="doLogin" class="check.x.com.SSOAction" method="doLogin">
            <result name="success" type="redirect">${gotoUrl}</result>
            <!-- 需要记录返回去的位置才是比较理想的 -->
        </action>
    </package>
    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="com.imooc.demo1.Demo1Action" method="main">
            <result name="success">/success1.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="com.imooc.demo2.Demo2Action" method="main">
            <result name="success">/success2.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
</struts>

编写登录校验接口

放到另一个应用下来校验:check.x.com下

public class SSOAction extends ActionSupport{

    private String username;
    private String password;
    private String gotourl;
    private String cookieName;
    private String cookieValue;
    getter/setter
    void checkCookie() throws IOException{
        boolean ok = SSOCheck.checkCookie(cookieName,cookieValue);
        String result = "0";
        if(ok){
            result="1";
        }
        HttpServerletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
        //把校验结果发给你就可以了
    }
}

public class SSOCheck {

    public static boolean checklogin(String username,String password){
        if(username.equals("123")&& password.equals("123")){
            return true;
        }
        return false;
    }
    
    public static boolean checkcookie(String cookieName,String cookieValue){
        
        if(cookieName.equals("ssocookie")&& cookieValue.equals("sso")){
            return true;
        }
        
        return false;
    }

编写demo1和demo2 的主页
HttpURLConnection doGetUtils
String doget(String url,String cname,String cval){
    HttpURLConnection httpURLConnection = null;
    StringBuffer sb = new StringBuffer();
    try{
        URL url = new URL(url+"?cookiename="+cname+"&cookieval="+cval);
        httpURLConnection =(HttpURLConnection) url.openConnection();
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.connect();
        InputStream in = httpURLConnection.getInputStream();
        InputStreamReader is = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(is);
        String temp = null;
        while((temp=br.readLine())!=null){
            sb.append(temp);
        }
        br.close();
        is.close();
        in.close();
    
    }catch(IOException e){
        e.printStackTrace();
    }finally{
        if(httpURLConnection!=null){
            httpURLConnection.disconnect();
        }
    }
    return sb.toString();
}


public class Demo1Action extends ActionSupport{

    private String gotourl;
    public String main(){
        HttpServletRequest request = ServletActionContext.getRequest();
        Cookie[] cookies = request.getCookies();
        if(cookies!=null){
            for(Cookie cookie:cookies){
                if(cookie.getName().equals("ssocookie")&&
                        cookie.getValue().equals("sso")){
                    String result = doget("http://check.x.com/sso/checkcookie.action",
                            cookie.getName(), cookie.getValue());
                    if(result.equals("1")){
                        return SUCCESS;
                    }
                }
            }
        }
        gotourl = "http://demo1.x.com/demo1/main.action";
        return "login";
    }
    public String getGotourl() {
        return gotourl;
    }
    public void setGotourl(String gotourl) {
        this.gotourl = gotourl;
    }
    
    public String doget(String url,String cname,String cval){
        HttpURLConnection httpURLConnection = null;
        StringBuffer sb = new StringBuffer();
        try{
            URL urls =new URL(url+"?cookiename="+cname+"&cookieval="+cval);
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.connect();
            InputStream in  =  httpURLConnection.getInputStream();
            InputStreamReader is= new InputStreamReader(in);
            BufferedReader br = new BufferedReader(is);
            String temp = null;
            while((temp=br.readLine())!=null){
                sb.append(temp);
            }
            br.close();
            is.close();
            in.close();
            
        }catch (IOException c) {
            // TODO: handle exception
        }finally{
            if(httpURLConnection!=null){
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }



完全跨域的sso
http://www.a.com/demo1/main.action
http://www.b.com/demo2/main.action
统一校验接口
http://www.x.com/sso/checkCookie.action

修改hosts文件
127.0.0.1 www.a.com
127.0.0.1 www.b.com
127.0.0.1 www.x.com



























  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值