E81086713E446D36F62B2AA2A3502B5EB155

Java杂家

杂七杂八。。。一家之言

BlogJava 首页 新随笔 联系 聚合 管理
  141 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks

考虑这样一个使用场景,假如要查看所有进入weblogic上请求的(注意不是访问某个特定web app的)一些请求头是否设置,如果没有设置则返回以定制的页面.否则正常处理.
这么一个简单的需求在Tomcat下是很容易实现的,但是在weblogic下就比较奢侈了.
你可能想到weblogic中:
1)weblogic.security.net.ConnectionFilter
但是在ConnectionFilter中得到的信息太少了,根本不能查看请求头

2)提供IdentityAsserter Provider,实现weblogic.security.spi.IdentityAsserter
这个可以拿到看到你配置的特定的请求头了,但是还是不能查看完整请求,也不能写Response
weblogic9.1好像提供weblogic.security.spi.IdentityAsserterV2,这个类的assertIdentity()方法有个ContextHandler类,通过它可以访问到
HttpServletRequest,HttpServletResponse了,但是为了启用你的IdentityAsserter Provider,你必须在你要拦截的web应用中配置安全属性(web.xml)并且还得auth-method为CLIENT-CERT模式.
这种方式一般用来实现单点登陆.

那么,难道还有别的方法?
是的,下面介绍一种特别的方法(基于weblogic 7.1的,weblogic8.1也可以,但是要改动一点点)

weblogic domain的配置文件config.xml在<domain>元素下有一个<StartupClass>元素,用于设置一个容器启动类
  <StartupClass ClassName="com.yovn.labs.wls.startup.Startup"
        FailureIsFatal
="true" LoadBeforeAppDeployments="true"
        Name
="MyStartup Class" Targets="myserver"/>

意义一目了然,就不多说了.

那么,在com.yovn.labs.wls.startup.Startup中干什么呢?

先通过weblogic.socket.JVMSocketManager.java来看看Weblogic是怎么管理Socket的
package weblogic.socket;

import weblogic.com.ProtocolHandlerDCOM;
import weblogic.iiop.ProtocolHandlerIIOP;
import weblogic.iiop.ProtocolHandlerIIOPS;
import weblogic.ldap.ProtocolHandlerLDAP;
import weblogic.rjvm.Protocol;
import weblogic.rjvm.t3.ProtocolHandlerT3;
import weblogic.rjvm.t3.ProtocolHandlerT3S;
import weblogic.servlet.internal.ProtocolHandlerHTTP;
import weblogic.servlet.internal.ProtocolHandlerHTTPS;
import weblogic.utils.AssertionError;


public final class JVMSocketManager
{

    
private static final boolean DEBUG = false;
    
private static final ProtocolHandler discHandlers[];
    
public static final int numDiscProtocols;
    
private static final ProtocolHandler defHandlers[];
    
public static final int numDefProtocols;

    
public JVMSocketManager()
    {
    }

    
static ProtocolHandler[] getDefaultProtocolHandlers()
    {
        
return defHandlers;
    }

    
static ProtocolHandler[] getDiscriminatingProtocolHandlers()
    {
        
return discHandlers;
    }

    
public static int[] makePortArray(int i, int j, int k, int l, int i1, int j1, int k1)
    {
        
int ai[] = new int[7];
        ai[
0= i;
        ai[
1= j;
        ai[
2= k;
        ai[
3= l;
        ai[
4= i1;
        ai[
5= j1;
        ai[
6= k1;
        
return ai;
    }

    
static
    {
        
try
        {
            discHandlers 
= (new ProtocolHandler[] {
                ProtocolHandlerT3S.theHandler(), ProtocolHandlerT3.theHandler(), ProtocolHandlerIIOPS.theHandler(), ProtocolHandlerIIOP.theHandler(), ProtocolHandlerDCOM.theHandler(), ProtocolHandlerLDAP.theHandler()
            });
            numDiscProtocols 
= discHandlers.length;
            defHandlers 
= (new ProtocolHandler[] {
                ProtocolHandlerHTTPS.theHandler(), ProtocolHandlerHTTP.theHandler()
            });
            numDefProtocols 
= defHandlers.length;
        }
        
catch(Throwable throwable)
        {
            
throw new AssertionError("Protocol registration failed", throwable);
        }
    }
}

很显然,它的protocol handler是通过一个final 数组来管理,加入我在Startup类里修改defHandlers里的第二个元素,那么处理HTTP请求的protocol handler就可以被换掉了
来看我们的代码:

package com.yovn.labs.wls.startup;

import java.lang.reflect.Field;

import weblogic.socket.JVMSocketManager;
import weblogic.socket.ProtocolHandler;

import com.yovn.labs.wls.protocol.ProtocolHandlerHTTP;



/**
 * 
@author yovn
 *
 
*/
public class Startup {

    
/**
     * 
@param args
     * 
@throws NoSuchFieldException
     * 
@throws SecurityException
     
*/
    
public static void main(String[] args) throws Exception {
        Field f
=JVMSocketManager.class.getDeclaredField("defHandlers");
        f.setAccessible(
true);
        ProtocolHandler[] handlers
=(ProtocolHandler[])f.get(null);
       
        System.err.println(
"[Startup]===================================================:Mystart up class!");
        System.err.println(
"[Startup]===================================================:default http handler is "+handlers[1]+"!");
        handlers[
1]=ProtocolHandlerHTTP.theHandler();
        System.err.println(
"[Startup]===================================================:now, http handler is "+handlers[1]+"!");

    }

}


好,现在HTTP Protocol Handler换成我们的 com.yovn.labs.wls.protocol.ProtocolHandlerHTTP类了
接下来就看我们的handler代码了
package com.yovn.labs.wls.protocol;
import java.io.IOException;
import java.net.ProtocolException;
import java.net.Socket;

//import weblogic.protocol.configuration.NetworkChannel;//在weblogic8.1中
import weblogic.rjvm.NetworkChannel;//在weblogic7.1中
import weblogic.socket.MuxableSocket;
import weblogic.socket.ProtocolHandler;
import weblogic.utils.io.Chunk;



public class ProtocolHandlerHTTP
    
implements ProtocolHandler
{

    
private static ProtocolHandler theOne = null;
    
protected static String PROTOCOL_NAME = "HTTP";
 

    
public ProtocolHandlerHTTP()
    {
    }

    
public static ProtocolHandler theHandler()
    {
        
if(theOne == null)
            
synchronized(ProtocolHandlerHTTP.class)
            {
                
if(theOne == null)
                    theOne 
= new ProtocolHandlerHTTP();
            }
        
return theOne;
    }

   

    
public int getHeaderLength()
    {
        
return 0;
    }

    
public String getProtocolName()
    {
        
return PROTOCOL_NAME;
    }

    
public boolean claimSocket(Chunk chunk, Socket socket)
        
throws IOException
    {
        
return true;
    }

    
public boolean canReadHeaders(byte abyte0[], int i)
    {
        
return true;
    }

    
public MuxableSocket createSocket(Chunk chunk, Socket socket, NetworkChannel networkchannel)
        
throws IOException
    {
        
if(!networkchannel.isProtocolEnabled(2&& !networkchannel.isDefaultChannel())
        {
            
throw new ProtocolException("HTTP is disabled");
        } 
else
        {
            MuxableSocketHTTP muxablesockethttp 
= new MuxableSocketHTTP(chunk, socket, networkchannel);
            
return muxablesockethttp;
        }
    }

  

}

这段代码在要求创建MuxableSocket时创建了一个com.yovn.labs.wls.protocol.MuxableSocketHTTP,这个类里面就是我们做一些有意义的事情的地方了
来看代码:

package com.yovn.labs.wls.protocol;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.Socket;
import java.net.SocketException;

import weblogic.rjvm.NetworkChannel;
import weblogic.servlet.internal.RequestParser;
import weblogic.servlet.internal.ServletRequestImpl;
import weblogic.socket.MaxMessageSizeExceededException;
import weblogic.socket.MuxableSocket;
import weblogic.utils.io.Chunk;

/**
 * 
@author yovn
 *
 
*/
public class MuxableSocketHTTP implements MuxableSocket {

    
private final MuxableSocket delegate;//the internal implementation
    private Field countF;
    
private Field bufF;
    
private Field sockF;
   
   

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#dispatch()
     
*/
    
public void dispatch() {

        
try {
            
byte[] buf=(byte[])bufF.get(delegate);
            
int count=countF.getInt(delegate);
           
            ServletRequestImpl servletrequestimpl 
= new ServletRequestImpl();
            RequestParser requestparser 
= new RequestParser(servletrequestimpl,buf, count);
            
if(requestparser.parse()<0)
            {
                Socket sock
=(Socket)sockF.get(delegate);
                OutputStream out
=sock.getOutputStream();
                sendError(out,
500,"Internal error");
                out.close();
                
return;
            }
            String accessV
=servletrequestimpl.getHeader("access");
            
if(accessV==null)
            {
                Socket sock
=(Socket)sockF.get(delegate);
                OutputStream out
=sock.getOutputStream();
                sendMessage(out,
"You have not set 'access' header");
                out.close();
                
return;
            }
//            System.out.println("+================================request first Line:"+servletrequestimpl.getFirstLine()+",request:"+servletrequestimpl.getRequestURI());
        } catch (Exception e) {
           
            e.printStackTrace();
        }
       
       
        delegate.dispatch();
       

    }
   
     
void  sendMessage(OutputStream out,String msg) throws IOException
     {
         String s
="HTTP/1.1 "+200+" OK\r\n\r\n";
         out.write(s.getBytes());
         out.write(msg.getBytes());
         out.flush();
     }
     
     
void  sendError(OutputStream out,int code,String msg) throws IOException
     {
         String s
="HTTP/1.1 "+code+" "+msg+"\r\n\r\n";
         out.write(s.getBytes());
         out.flush();
     }
   
   
   
     
public MuxableSocketHTTP(Chunk chunk1, Socket socket, NetworkChannel networkchannel)
     
throws IOException
     {
     
//create our delegation first
         delegate=new weblogic.servlet.internal.MuxableSocketHTTP(chunk1,socket,networkchannel);
         
         
//initiate private fields
         try {
            countF
=weblogic.servlet.internal.MuxableSocketHTTP.class.getDeclaredField("count");
            bufF
=weblogic.servlet.internal.MuxableSocketHTTP.class.getDeclaredField("buf");
            sockF
=weblogic.servlet.internal.MuxableSocketHTTP.class.getDeclaredField("sock");
            sockF.setAccessible(
true);
            countF.setAccessible(
true);
            bufF.setAccessible(
true);
        } 
catch (SecurityException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (NoSuchFieldException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }
     }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#endOfStream()
     
*/
    
public void endOfStream() {
        delegate.endOfStream();

    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getBuffer()
     
*/
    
public byte[] getBuffer() {
       
        
return delegate.getBuffer();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getBufferOffset()
     
*/
    
public int getBufferOffset() {
       
        
return delegate.getBufferOffset();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getCompleteMessageTimeoutMillis()
     
*/
    
public int getCompleteMessageTimeoutMillis() {
   
        
return delegate.getCompleteMessageTimeoutMillis();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getIdleTimeoutMillis()
     
*/
    
public int getIdleTimeoutMillis() {
       
        
return delegate.getIdleTimeoutMillis();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getMaxMessageSize()
     
*/
    
public int getMaxMessageSize() {
   
        
return delegate.getMaxMessageSize();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getRawSocket()
     
*/
    
public Socket getRawSocket() {
   
        
return delegate.getRawSocket();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getReRegisterMX()
     
*/
    
public MuxableSocket getReRegisterMX() {
   
        
return delegate.getReRegisterMX();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getSocket()
     
*/
    
public Socket getSocket() {
   
        
return delegate.getSocket();
    }

    
public void ensureForceClose() {
        delegate.ensureForceClose();
       
    }

    
public boolean isClosed() {
   
        
return delegate.isClosed();
    }

   
    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#getSocketInputStream()
     
*/
    
public InputStream getSocketInputStream() {
       
        
return delegate.getSocketInputStream();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#hasException(java.lang.Throwable)
     
*/
    
public void hasException(Throwable arg0) {
        delegate.hasException(arg0);

    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#incrementBufferOffset(int)
     
*/
    
public void incrementBufferOffset(int arg0)
            
throws MaxMessageSizeExceededException {
        delegate.incrementBufferOffset(arg0);

    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#isMessageComplete()
     
*/
    
public boolean isMessageComplete() {
       
        
return delegate.isMessageComplete();
    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#setReRegisterMX(weblogic.socket.MuxableSocket)
     
*/
    
public void setReRegisterMX(MuxableSocket arg0) {
        delegate.setReRegisterMX(arg0);

    }

    
/* (non-Javadoc)
     * @see weblogic.socket.MuxableSocket#setSoTimeout(int)
     
*/
    
public void setSoTimeout(int arg0) throws SocketException {
   
        delegate.setSoTimeout(arg0);
    }

   


}


主体在dispatch()方法里,我们先创建weblogic内部的MuxableSocketHttp作为我们真正的实现,然后利用RequestParser,ServletRequestImpl来解析
HTTP请求,解析后就可以查看详细的请求内容了,我们简单的检查一下一个特定的request header是否设置如果没有,则告知没有设置,否则正常处理.

好了,把上面的程序编译,打包,扔到你的weblogic domain下,修该domain的config.xml如本文开头所示.把你打好的包,加入你的weblogic类路径,启动weblogic.

Ok,现在你在浏览器里随便请求一个weblogic上的地址,你会看到如下页面:

You have not set 'access' header

我们再来写个测试程序,如下:

package com.yovn.labs.wls.test;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 
@author yovn
 *
 
*/
public class TestAccess {

    
/**
     * 
@param args
     
*/
    
public static void main(String[] args)throws Exception {
        URL url
=new URL("http://localhost:7001/console");
        HttpURLConnection conn
=( HttpURLConnection)url.openConnection();
        conn.addRequestProperty(
"access""pass");
        InputStream in
=conn.getInputStream();
        
int len=0;
        ByteArrayOutputStream bao
=new ByteArrayOutputStream(1024*4);
        
byte[] bytes=new byte[1024];
        
while((len=in.read(bytes))>0)
        {
            bao.write(bytes,
0,len);
        }
       
        in.close();
        conn.disconnect();
       
        System.out.println(bao.toString());
       
       
       

    }

}

由于这个程序设置了'access'请求头,所打印出来内容就是正常请求该地址所产生的内容.

下载:
code and jar


posted on 2007-04-03 22:48 DoubleH 阅读(7939) 评论(2)  编辑  收藏

Feedback

# re: WebLogic中拦截全局http请求[未登录] 2007-04-04 15:20 azure
very good  回复  更多评论
  

# re: WebLogic中拦截全局http请求[未登录] 2011-09-13 21:47 111
请问楼主,在WebSphere完成上述功能,该如何做呢?  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: