欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Weblogic中通过IdentityAsserter实现SSO

程序员文章站 2022-04-16 23:34:08
...
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 = "&quot;com.huawei.netforce.security.sso.ImepIdentityAsserterProviderImpl&quot;"
/>

<MBeanAttribute 
	Name = "Description" 
	Type = "java.lang.String"
	Writeable = "false" 
	Default = "&quot;ImepIdentityAsserter Identity Assertion Provider&quot;"
/>

<MBeanAttribute 
	Name = "Version" 
	Type = "java.lang.String"
	Writeable = "false" 
	Default = "&quot;1.0&quot;"
/>

<MBeanAttribute 
	Name = "SupportedTypes" 
	Type = "java.lang.String[]"
	Writeable = "false" 
	Default = "new String[] {&quot;ImepToken&quot;}"
/>

<MBeanAttribute 
	Name = "ActiveTypes" 
	Type = "java.lang.String[]"
	Default = "new String[] {&quot;ImepToken&quot;}"
/>
</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);
        }
    }