7777">
2、登录的Servlet程序如下:
/**
*用户登录
*/
publicclassLoginServletextendsHttpServlet{
publicvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)
throwsServletException,IOException{
doPost(req,resp);
}
publicvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)
throwsServletException,IOException{
Stringnm=req.getParameter("name");
Stringpwd=req.getParameter("pwd");
Stringchk=req.getParameter("chk");//是否选中了7天自动登录
Stringforward="/index.jsp";
if(nm!
=null&&!
nm.trim().equals("")&&nm.startsWith("it")//用户名是it开始,且密码是pwd开始的可以登录
&&pwd!
=null&&!
pwd.trim().equals("")&&
pwd.startsWith("pwd")){
System.err.println("登录成功。
。
。
。
。
");
forward="/jsps/welcome.jsp";
//无论如何,都要设置cookie,如果没有选择自动登录,则只在当前页面的跳转时有效,否则设置有效期间为7天。
Cookiecookie=newCookie("autologin",nm+"@"+pwd);
cookie.setPath("/");//如果路径为/则为整个tomcat目录有用
cookie.setDomain("");//设置对所有*为后缀的域名效
if(chk!
=null){
inttime=1*60*60*24*7;//1秒*60=1分*60分=1小时*24=1天*7=7天
cookie.setMaxAge(time);
}
resp.addCookie(cookie);
req.getSession().setAttribute("user",nm);
}else{
System.err.println("登录不成功。
。
。
。
。
。
");
}
req.getRequestDispatcher(forward).forward(req,resp);
}
}
3、自动登录的Filter程序如下:
/**
*自动登录
*/
publicclassAutoLoginimplementsFilter{
publicvoiddestroy(){}
publicvoiddoFilter(ServletRequestreq,ServletResponseresp,
FilterChainchain)throwsIOException,ServletException{
System.err.println("开始自动登录验证.....");//此类中应该对登录的servlet直接放行。
根据判断url决定。
HttpServletRequestrequ=(HttpServletRequest)req;
HttpSessions=requ.getSession();
if(s.getAttribute("user")!
=null){//如果用户已经登录则直接放行
System.err.println("用户已经登录,没有必须要再做自动登录。
。
。
。
");
}else{
Cookie[]cookies=requ.getCookies();
if(cookies!
=null){
for(Cookieck:
cookies){
if(ck.getName().equals("autologin")){//是否是自动登录。
。
。
。
System.err.println("自动登录成功。
。
。
。
。
");
Stringval=ck.getValue();
String[]vals=val.split("@");
s.setAttribute("user",vals[0]);
}
}
}
}
chain.doFilter(req,resp);
}
publicvoidinit(FilterConfigfilterConfig)throwsServletException{}
}
4、正常退出的Servlet如下
/**
*安全退出删除Cookie
*/
publicclassLoginOutServletextendsHttpServlet{
publicvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)
throwsServletException,IOException{
HttpSessions=req.getSession();//获取Session
Cookiecookie=newCookie("autologin","");//必须声明一个完全相同名称的Cookie
cookie.setPath("/");//路径也要完全相同
cookie.setDomain("");//域也要完全相同
cookie.setMaxAge(0);//设置时间为0,以直接删除Cookie
resp.addCookie(cookie);
s.removeAttribute("user");
System.err.println("安全退出。
。
。
。
。
");
resp.sendRedirect(req.getContextPath()+"/index.jsp");
}
}
5、关于自动登录的一些思考
为了让单点登录,变成可配置的功能,可以将保存Cookie的代码,放到自动登录的Filter中实现。
如果配置自动登录的Filter则同时实现闪单点登录,否则不加实现。
2、SSO示例程序配置
在CAS的主页上,可以看到CAS服务器,和客户端配置的完整过程,根据提示,完全可以配置成功服务器和客户端。
同时,在CAS上也可以找到服务器端的程序和客户端的程序,都是已经配置好的,对于初步学习来说,完全可以直接取来配置测试。
以下就是直接使用CAS官方提供的示例服务器和示例客户端配置一个单点登录的示例:
Jasig主页:
http:
//www.jasig.org/cas/download
第一步:
先下载cas的服务器端支持包:
cas-server3.xx.zip
第二步:
下载cas有客户端支持包。
Cas-client.zip
第三步:
下载客户端的示例程序,这个不太好找。
需要有点耐心
以下是下载的超连接:
https:
//wiki.jasig.org/display/CASC/JA-SIG+Java+Client+Simple+WebApp+Sample
第四步:
解压cas-server.zip如下图,并从中找到服务器端war文件
服务器端程序一般不用我们完成,但需要做一点小小的修改,cas的服务器端程序由spring+Springwebflow+cas写成。
全部使用spring配置文件。
它就是一个用户登录验证、发售票据的中心。
相当于TicketOffice(售票处)。
第五步:
分别建立三个虚拟主机。
一个是服务器主机,和两个客户端虚拟主机。
1、修改etc/hosts文件:
2、修改tomcat/conf/server.xml配置文件,增加虚拟主机目录,同时将服务器的端口修改成80。
3、在tomcat的根目录下,分别建立三个目录,即server、bbs、news。
在三个目录下,分别都建立一个ROOT(ROOT是tomcat的主默认主页目录)文件夹。
将cas-server.xx.war解压后散放到/tomcat/server/ROOT目录下。
如下图:
注意目录结构,是散放到ROOT的目录下。
第六步:
先测试服务器是否可以正常使用
启动tomcat,在地址栏输入:
登录:
请先保证在单个服务器上登录可以登录成功。
如果不能登录成功,请重复前面的配置。
第七步:
配置两个客户端
将下载的
文件分别解压到tomcat/bbs/ROOT目录下和tomcat/news/ROOT目录下。
注意是散放到ROOT目录下。
由于在mywebapp.war中并没有放置依赖的jar文件,所以,还需要我们添加它所依赖的jar文件,为此我为大家准备了已经放放置好的
mywebapp.war文件。
放置好的目录结构如下:
(bbs程序同,不再上图)
WEB-INF/lib目录下的包如下:
这两个包,在cas-client.rar文件中都可以找到。
此处,你可以启动一个tomcat,如果启动成功,则进入下一步。
第八步:
修改客户端的配置文件
当使用登录客户端受保护的资源时,如果发现还没有登录,则会重定向到服务器(售票处)请求登录验证,登录成功后即会获取一张票据,服务器会携带这张票据再重定向到客户端页面。
修改客户端的web.xml配置文件,让它在登录时,知道去哪台服务器:
注意将里面的https全部修改成http。
修改的部分主要分为两块:
1:
修改登录重定向过虑器,它用于保护受保护的资源,如果发面用户在访问受保护的资源时,用户还没有登录,则会重定向到服务器,要求用户登录:
2、修改验证过虑器,它的主要作用是接收服务器发送的Ticket,进行验证
其他没有说明的部分,请不要修改。
请参考上面的实现配置另一个项目的web.xml文件。
第九步:
测试登录
目前还不能实现单点登录。
但可以对任意的一个客户端进行登录验证。
1、在地址栏输入
点击访问受保护的页面:
gottoprotectedarea
将重定向到服务器请求登录:
登录成功后即重定回原请求页面:
第十步:
配置可以单点登录
Cas服务器都是用spring配置文件配置而成。
且使用了cookie技术。
在ticketGrantingTicketCookieGenerator.xml文件中,保存了cookie的生成方式及有效时间。
注意,这是在server服务器上的spring配置文件。
打开此文件,修改成以下内容:
说明:
false是指支持http协议登录。
默认为true,支持https登录。
3600中cookie保存在本地的时间,默认为-1即浏览器缓存。
cookiePath是cookie的path设置。
第十一步:
单点登录测试
修改了上面文件后,即可测试是否可以从一个点的登录,即可以访问两个网站时都显示先登录的姓名:
先输入
登录
登录成功:
在地址栏直接输入:
可以看到,显示的是news用户名,即之前在上登录的用户名,即实现单点登录。
好了,以上步骤,你同学们先自己完成,如果可以配置成功,再进入下一步。
3、CAS单点登录流程图
4、在Eclipse环境中开发SSO
为了文件书写代码,我们需要将cas-server导入到eclipse环境中:
1、建立一个新的web项目:
2、将cas-server.war文件中的文件放到Eclipse web项目的相关目录下:
注意:
src下的文件需要到cas-server/WEB-INF/classes下单独copy.
3、重新设置虚拟目录
将原来的虚拟主机目录删除。
配置新的虚拟目录,并通过形式指定Eclipse下的项目为项目的根目录,如下:
Host的name保先原地址不变,这样就没有必要修改hosts文件了。
在tomcat的根目录下,创建一个casServer目录,里面什么也不用放即可。
通过指定根目录为Eclipse中的项目。
测试是否可以访问。
4、建立客户端项目-两个
项目中使用了jstl.jar包,应该放到WEB-INF/lib目录下。
5、配置两个项目的虚拟目录
将原来配置的两个虚拟主机目录删除,然后使用配置新的项目。
如下:
6、准备cas-client.jar包
7、声明受保护的资源并在web.xml中配置
此处可以完全参考原有客户端项目的配置。
(略)
运行测试进入下一步。
5、在客户端面获取用户的基本信息-name。
(重点)
1、Cas在登录成功后会通过socket向客户端传递用户信息。
一般情况下就是用户名而已。
2、cas客户端的request对象是经过包装的org.jasig.cas.client.util.HttpServletRequestWrapperFilter$CasHttpServletRequestWrapper。
3、在用户成功后,客户端的过虑器,会将用户的信息封装成java.security.Principal的子封装到Assertion后放到Session中。
关于Assertion对象的结构图,请见后面的部分。
以下是在客户端的页面上如何获取用户名信息的多种方式:
那么,如何才可以返回更多用户的信息呢。
如返回用户和用户名和id?
后面的章节将会讲到。
6、修改服务器的登录验证规则
1、使用配置的用户名和密码
目前服务器的验证方式为用户和密码相同即为登录成功。
这并不符合我们的业务需求,大多数应用都是通过查询数据库获取用户名和密码的。
那我们又如何设置从数据库获取用户名和密码呢?
为了便于理解,我先将服务器的登录方式修改为配置的。
而后再修改成通过数据库进行验证的。
修改配置文件:
/WEB-INF/deployerConfigContext.xml。
在这个配置文件中,保存了多个用户认证登录的验证方式,只要有一种验证通过即可以登录成功。
在...属性内部,通过配置若干的AuthenticationHandler的子类,可以改变登录认证方式。
也可以增加认证方式,只要在用户登录时,有一种登录方式是可行的,即可以登录成功。
认证类的继承关系如下:
默认已经配置了最后一个类即SimpleTestUsernamePasswordAuthenticationHandler。
此类验证用户名和密码是否一致。
Cas为了我们提供了可以直接配置用户名和密码类:
即org.jasig.cas.adaptors.generic.AcceptUsersAuthenticationHandler。
此类并没有包含到默认的服务器代码中,需要到cas-server/models/中查找名为:
cas-server-support-generic-3.4.11.jar的jar文件,并添加到WEB-INF/lib目录下。
如下图所示,正是名为generic的jar包。
(后面如果需要数据库连接的,还需要jdbc的jar包)
将此jar包放到lib目录下后,类的层次关系如下:
此类接收一个map当作用户名和密码的集合列表:
在/WEB-INF/deployerConfigContext.xml配置文件中的元素中,删除原来的用户名与密码相同的认证,即:
--class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler"/>-->
然后在相同的位置配置:
AcceptUsersAuthenticationHandler类:
配置如下:
登录测试:
直接在配置文件中配置用户名和密码:
可选的加密
--通用的认证管理器,通过一个文件或是一个map配置用户名和密码-->
--1234MD5:
4321-->
--4321:
md5:
-->
--可选的使用md5进行加密-->
2、自己书写验证规则-颠倒的用户名和密码
1、所有的认证类都是AuthenticationHandler的子类,于是我们可以自己开发基于任何规则的验证。
2、基于用户名和密码的认证,则应该继承AbstractUsernamePasswordAuthenticationHandler。
3、代码如下:
packagecn.itcast.handler;
importorg.jasig.cas.authentication.handler.AuthenticationException;
importorg.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
importorg.jasig.cas.authentication.principal.UsernamePasswordCredentials;
/**
*颠倒的用户名和密码即可以登录
*@author传智播客-王健
*credentials:
凭据
*/
publicclassMyReverseUsernamePasswordHandler
extendsAbstractUsernamePasswordAuthenticationHand