weblogic8实现SSO的一种简单方案,就是通过IdentityAsserter解决。
步骤一、SSO目标配置
<security-constraint> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.do</url-pattern> <url-pattern>*.html</url-pattern> <url-pattern>*.htm</url-pattern> <url-pattern>*.doc</url-pattern> <url-pattern>*.xls</url-pattern> <url-pattern>*.xlsx</url-pattern> <url-pattern>*.zip</url-pattern> <url-pattern>*.rar</url-pattern> <url-pattern>*.jpg</url-pattern> </web-resource-collection> <auth-constraint> <role-name>secrole</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>CLIENT-CERT</auth-method> <realm-name>myrealm</realm-name> </login-config> <security-role> <role-name>secrole</role-name> </security-role>
步骤二、创建Identity Assertion Provider
1、产生MDF:ImepIdentityAsserter.xml
<?xml version="1.0" ?> <!DOCTYPE MBeanType SYSTEM "commo.dtd"> <MBeanType Name = "ImepIdentityAsserter" DisplayName = "ImepIdentityAsserter" Package = "com.huawei.netforce.security.sso" Extends = "weblogic.management.security.authentication.IdentityAsserter" PersistPolicy = "OnUpdate" > <MBeanAttribute Name = "ProviderClassName" Type = "java.lang.String" Writeable = "false" Default = ""com.huawei.netforce.security.sso.ImepIdentityAsserterProviderImpl"" /> <MBeanAttribute Name = "Description" Type = "java.lang.String" Writeable = "false" Default = ""ImepIdentityAsserter Identity Assertion Provider"" /> <MBeanAttribute Name = "Version" Type = "java.lang.String" Writeable = "false" Default = ""1.0"" /> <MBeanAttribute Name = "SupportedTypes" Type = "java.lang.String[]" Writeable = "false" Default = "new String[] {"ImepToken"}" /> <MBeanAttribute Name = "ActiveTypes" Type = "java.lang.String[]" Default = "new String[] {"ImepToken"}" /> </MBeanType>
java -DcreateStubs="true" weblogic.management.commo.WebLogicMBeanMaker -MDF ImepIdentityAsserter.xml -files d:\src
2、创建提供程序实现
import java.io.PrintStream; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.AppConfigurationEntry; import weblogic.management.security.ProviderMBean; import weblogic.security.spi.*; public class ImepIdentityAsserterProviderImpl implements AuthenticationProvider, IdentityAsserter { private static final String TOKEN_TYPE = "ImepToken"; private static final String TOKEN_PREFIX = "username="; private String description; public ImepIdentityAsserterProviderImpl() { } public AppConfigurationEntry getAssertionModuleConfiguration() { return null; } public IdentityAsserter getIdentityAsserter() { return this; } public AppConfigurationEntry getLoginModuleConfiguration() { return null; } public PrincipalValidator getPrincipalValidator() { return null; } public String getDescription() { return description; } public void initialize(ProviderMBean mbean, SecurityServices services) { System.out.println("ImepIdentityAsserterProviderImpl.initialize"); ImepIdentityAsserterMBean myMBean = (ImepIdentityAsserterMBean)mbean; description = myMBean.getDescription() + "\n" + myMBean.getVersion(); } public void shutdown() { } public CallbackHandler assertIdentity(String type, Object token) throws IdentityAssertionException { if(!"ImepToken".equals(type)) { String error = "ImepIdentityAsserterProviderImpl received unknown token type \"" + type + "\"." + " Expected " + "ImepToken"; throw new IdentityAssertionException(error); } if(!(token instanceof byte[])) { String error = "ImepIdentityAsserterProviderImpl received unknown token class \"" + token.getClass() + "\"." + " Expected a byte[]."; throw new IdentityAssertionException(error); } byte tokenBytes[] = (byte[])token; if(tokenBytes == null || tokenBytes.length < 1) { String error = "ImepIdentityAsserterProviderImpl received empty token byte array"; throw new IdentityAssertionException(error); } String tokenStr = new String(tokenBytes); if(!tokenStr.startsWith("username=")) { String error = "ImepIdentityAsserterProviderImpl received unknown token string \"" + type + "\"." + " Expected " + "username=" + "username"; throw new IdentityAssertionException(error); } else { String userName = tokenStr.substring("username=".length()); return new ImepCallbackHandlerImpl(userName); } } }
import java.io.IOException; import javax.security.auth.callback.*; public class ImepCallbackHandlerImpl implements CallbackHandler { private String userName; public ImepCallbackHandlerImpl(String aUserName) { userName = aUserName; } public void handle(Callback callbacks[]) throws IOException, UnsupportedCallbackException { for(int i = 0; i < callbacks.length; i++) { Callback callback = callbacks[i]; if(!(callback instanceof NameCallback)) throw new UnsupportedCallbackException(callback, "Unrecognized Callback"); NameCallback nameCallback = (NameCallback)callback; nameCallback.setName(userName); } } }
3、MJF打包
java weblogic.management.commo.WebLogicMBeanMaker -MJF ImepIdentityProvider.jar -files d:\src
4、服务端配置
把这个提供程序(ImepIdentityProvider.jar)复制到WL_HOME/server/lib/mbeantypes目录下,然后重新启动服务器。启动管理控制台,并导航到Security/myrealm Providers/Authentication节点。在可用验证器和身份确认器的列表中,应该可以找到“Configure a new ImepIdentityAsserter...”选项。选择这个选项并点击Create,就可以配置身份确认器了。在接下来的选项卡中,您将会注意到,支持的令牌类型被设置为ImepToken和对于ImepToken是活动的令牌。现在,必须重新启动服务器,从而使修改生效。
步骤三、测试
1、URLConnection测试
try { //test账户需要在myrealm中进行配置 String token = "username=test"; //是否需要编码可在控制台配置时取消,默认为BASE64编码 BASE64Encoder encoder = new BASE64Encoder(); String encodedToken = encoder.encodeBuffer(token.getBytes()); URL url = new URL("http://localhost:7001/app/index.jsp"); URLConnection connection = url.openConnection(); connection.setRequestProperty("ImepToken",encodedToken); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line = ""; while((line = in.readLine()) != null) { System.out.println(line); } } catch(Exception e) { e.printStackTrace(); }
2、SSO源测试
由于IdentityAsserter需要客户端提供令牌,故在请求SSO目标应用时,需要在cookie中增加ImepToken属性
SSO目标在接收token并redirect的servlet代码片段为:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String tokenValue = request.getParameter("token"); String redirect = request.getParameter("redirect"); if(StringUtils.isNotEmpty(tokenValue)) { //IdentityAsserterProvider从cookie或者header中取token Cookie cookie = new Cookie("ImepToken", tokenValue); response.addCookie(cookie); response.setHeader("ImepToken",tokenValue); //添加P3P策略主要解决iframe集成时浏览器阻止跨域cookie response.setHeader("P3P","CP=CAO PSA OUR"); response.sendRedirect(redirect); } }