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
什么是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