??xml version="1.0" encoding="utf-8" standalone="yes"?> 因ؓ工作需要接触到ssoQ据知目前多?/span>sso使用耉?/span>cas实现Q且发现使用cas真的是很单就可以做出一个单点登录系l来Q?/span>casq提供丰富的扩展功能Q对于扩展功能日后再l细研究Q这里只使用cas做一?/span>hello world来记录本人的学习q程Q如有幸被高人看刎ͼq望指出弊病Q不吝赐教?/span> 在?/span>cas之前最好对数字证书有所了解Q不了解也没有关p,跟着我的步骤也一样可以跑的通?/span> 需要的文gQ?/span> ü Jdk6 ü Tomcat ü cas-server-3.3.2 ü cas-client-3.1.9 下面?/span>keytool命o的一些常用方法,先在q里认识一下它们,一会儿会用的到?/span> 使用keytool命o生成密钥?/span> keytool -genkey -alias tomcat -keyalg RSA -dname "CN=pcma, OU=vanceinfo, O=vanceinfo, L=haidian, S=beijing, C=CN" -keystore c:"keystore5.jks CNQ主机名 OUQ组l单?/span> OQ组l?/span> LQ地?/span> SQ城?/span> CQ国?br /> 导出证书 keytool -export -file c:/server5.crt -alias tomcat -keystore c:"keystore5.jks 证书导入到客户?/span>jdk keytool -import -keystore "D:"Java"jdk1.6.0_14"jre"lib"security"cacerts" -file c:/server5.crt -alias tomcat 从密钥库中删除指定别名的证书 keytool -delete -noprompt -alias tomcat -keystore E:"apache-tomcat-6.0.20_2"conf"keystore2.jks 查看密钥库中的证?/span> keytool -list -v -keystore c:"keystore5.jks 使用keytool命o生成密钥库?/span> 配置%tomcat_home%/conf/server.xml?/span>tomcat支持SSL协议Qƈ指定密钥库?/span> <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystorePass="mashiguang" keystoreFile="${catalina.home}/conf/keystore5.jks"/> 解压~?/span>cas-server-3.3.2-release.zip文gQ在modules目录里找?/span>cas-server-webapp-3.3.2.war文gQ这是一个做好了?/span>cas服务端,我们做的sso helloword可以直接使用Q只需?/span>cas-server-webapp-3.3.2.war改了个简单点的名字,?/span>cas.warQ然后部|到tomcat卛_?/span> 览器访?/span>https://pcma:8443/casQ如果打开昄的是cas默认的登录页面,则表C服务端已部|完毕?/span> 新徏两个web工程Q用于模拟单点登录系l中的客LQƈ?/span>cas-client-3.1.9"modules里的jar包放?/span>web工程lib目录下,是主要的?/span>cas-client-core-3.1.9.jar文gQ把spring2.5也放?/span>lib目录下?/span> Web.xml文g <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/config/casContext.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- 负责用户认证 --> <filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <!-- CAS login 服务地址--> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>https://pcma:8443/cas/login</param-value> </init-param> <init-param> <param-name>renew</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>gateway</param-name> <param-value>false</param-value> </init-param> <!-- 客户端应用服务地址--> <init-param> <param-name>serverName</param-name> <param-value>http://pcma:8081</param-value> </init-param> </filter> <!--负责Ticket校验--> <filter> <filter-name>CAS Validation Filter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>cas.validationfilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> casContext.xml文g <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="cas.validationfilter" class="org.jasig.cas.client.validation.Cas10TicketValidationFilter"> <property name="ticketValidator"> <ref bean="cas10TicketValidator"/> </property> <property name="useSession"> <value>true</value> </property> <!-- 客户端应用服务地址--> <property name="serverName"> <value>http://pcma:8081</value> </property> <property name="redirectAfterValidation"> <value>true</value> </property> </bean> <bean id="cas10TicketValidator" class="org.jasig.cas.client.validation.Cas10TicketValidator"> <!-- q里参数?/span>cas服务器的地址--> <constructor-arg index="0" value="https://pcma:8443/cas" /> </bean> </beans> 新徏index.jsp文g <body> hello sso<br> <a >sso2</a>q个地址是另外一台机器上?/span>sso客户?/span> </body> 上面?/span>web.xml?/span>casContext.xml?/span>index.jsp是两个客L中的一个,另一个要Ҏ实际情况修改?/span> 最后不要忘记客L?/span>jdk要?/span>keytool命o导入证书文g?/span> 启动tomcatQ测试器讉Khttp://pcma:8081/ssoQ出?/span>casd面Q输入相同的用户名和密码卛_dQ登录成功后面自动跌{?/span>http://pcma:8081/ssoQ这时点击页面上?/span>sso2链接Q就可以自动dq蟩转到sso2应用?/span> 如果输入用户名密码后提示下面的异常,是因为部|客L?/span>jdk没有导入证书文g的原因?/span> javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target准备工作
证书
如果需要指定密钥有效期Q添?validity 365卛_Q单位是天,如:
keytool -genkey -alias tomcat -keyalg RSA -dname "xxxxx" -keystore xxxxx -validity 365配置tomcat
部vcas server
客户端?/span>cas client
试
源码
http://www.aygfsteel.com/Files/mashiguang/sso.zip
调用ejb?如果客户端和ejb不在同一个jvm,p讄InitialContext,不同的应用服务器InitialContext写法也不?
Context.INITIAL_CONTEXT_FACTORY:指定到目录服务的q接工厂
Context.PROVIDER_URL:目录服务提供者URL
//jboss:
Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"
Context.URL_PKG_PREFIXES, "org.jboss.naming"
Context.PROVIDER_URL, "localhost:1099"
//weblogic:
Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"
Context.PROVIDER_URL, "t3://localhost:7001"
//apusic(金蝶):
Context.INITIAL_CONTEXT_FACTORY, "com.apusic.jndi.InitialContextFactory"
Context.PROVIDER_URL, "rmi://localhost:6888"
//WebSphere:
Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"
Context.PROVIDER_URL, "iiop://localhost:900"
//J2EE SDK(J2EE RI):
Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory"
Context.PROVIDER_URL, "iiop://127.0.0.1:1050"
//SilverStream:
Context.INITIAL_CONTEXT_FACTORY, "com.sssw.rt.jndi.AgInitCtxFactory"
Context.PROVIDER_URL, "sssw://localhost:80"
//OC4J:
Context.INITIAL_CONTEXT_FACTORY, "com.evermind.server.rmi.RMIInitialContextFactory"
Context.PROVIDER_URL, "ormi://127.0.0.1/"
//WAS5:
Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"
Context.PROVIDER_URL, "iiop://localhost:2809"
常用JNDI服务提供者连接工?
Filesystem: Com.sun.jndi.fscontext.FSContextFactory或者com.sun.jndi.fscontext.RefFSContextFactory
LDAPv3: Com.sun.jndi.ldap.LdapCtxFactory
NDS: com.novell.naming.service.nds.NdsInitialContextFactory
NIS: com.sun.jndi.nis.NISCtxFactory
RMI registry: com.sun.jndi.rmi.registry.RegistryContextFactory
IBM LDAP服务提供? com.ibm.jndi.LDAPCtxFactory
BEA 名字服务提供? weblogic.jndi.WLInitialContextFactory
JBOSS名字服务提供? org.jnp.interfaces.NamingContextFactory
W一D代码不成立,而第二段代码成立的原因是:自动打包
自动打包规范要求boolean,byte,char≤127,介于-128→127之间的short和int被包装到固定的对象中.
打包和拆包是~译器认可的Q而不是虚拟机Q编译器在生成类的字节码Ӟ插入必要的方法调用,虚拟机只是执行这些字节码?/p>
W三D代码不用多说肯定不成立.
发送简单的文字邮g:
创徏多个EmailAttachment对象,q调用MultiPartEmail.attach();可以发送多个附?
发送HTML格式的邮?
发送html格式的邮件和单邮件的区别在创徏HtmlEmail对象
q用email.setHtmlMsg(String)或email.setMsg(String)把含有html标签的字W串赋给email对象.
HtmlEmail对象q有一个setTextMsg(String)Ҏ,q个Ҏ参数里的html标签会被当做普通字W处?不会被解析成html元素.
更详l内容可以看apache commons-email的用h?/a>.
Struts本n有一套完善的防止重复提交表单?strong>Token(令牌)机制Q但W者目前的目自写的framework没有用到StrutsQ故也得自写防止用户因ؓ后退或者刷新来重复提交表单内容的Token机制。不难,Ҏ实现?/p>
实现原理Q一致性。jsp生成表单Ӟ在表单中插入一个隐?lt;input>字段Q该字段是保存在页面端的token字符Ԍ同时把该字符串存入session中。等到用h交表单时Q会一q提交该隐藏的token字符丌Ӏ在服务器端Q查看下是否在session中含有与该token字符串相{的字符丌Ӏ如果有Q那么表明是W一ơ提交该表单Q然后删除存放于session端的token字符Ԍ再做正常业务逻辑程Q如果没有,那么表示该表单被重复提交Q做非正常流E处理,可以警告提示也可以什么也不做?/p>
看代码?/p>
首先?strong>Tokenȝ。类很简单,而且主要Ҏ都给doc注释?/p>
怎么使用Q?/font>
在jsp面端?/strong>
首先import该类Q?/p>
<%@ page import="com.paizuo.framework.util.Token" %>
表单包含隐藏的token字符?
在Server端action中进行检验?/strong>
完毕?/p>