Java authentification (Was Getting the http username/password for a part)

Koos Vriezen koos.vriezen at xs4all.nl
Sat May 3 18:49:28 BST 2003


On Sat, 3 May 2003, Koos Vriezen wrote:

> For cookie based authentication the only way seems to
> implement a HttpURLConnection and create it in a URLStreamHandlerFactory
> set by java.net.URL.setURLStreamHandlerFactory.
> For this, I revamped the KJavaDownloader. It was used for the
> KJASClassLoader a long time ago. I changed it for use of HttpURLConnection.
> It already seems to work nicely, though lot is not implemented yet (like
> POST's). Benefit are caching over jvm sessions and finally got webmin
> applets to work.

It's quite easy now to support other protocols as well. Attached one that
allows opening a html page from a ftp site that contains applets (smb/fish
should be added as well).
Using java default URLStreamHandlerFactory or the one that uses kio, is
just one call. A good candidate for a config option imo.

 >
> Comments?
>
> Koos
>
-------------- next part --------------
package org.kde.kjas.server;

import java.net.*;
import java.io.*;
import java.util.*;
import java.security.*;
/**
 * ClassLoader used to download and instantiate Applets.
 */

class KIOConnection
{
    final static int DATA = 0;
    final static int FINISHED = 1;
    final static int ERRORCODE = 2;

    protected static int id = 0;
    static Hashtable jobs = new Hashtable();

    Thread thread = null;

    protected boolean connected = false;
    protected String jobid = null;
    protected LinkedList data = new LinkedList ();
    protected int errorcode = 0;
    protected boolean finished = false;
    protected URL url;

    void checkConnected() throws IOException {
        if (!connected)
            throw new IOException("not connected");
    }
    protected boolean haveError() {
        return errorcode != 0;
    }

    class KJASOutputStream extends OutputStream {
        KJASOutputStream() {
        }
        public void write(int b) throws IOException {
            throw new IOException("not implemented");
        }
        public void close() throws IOException {
            checkConnected();
            disconnect();
        }
        public void flush() throws IOException {
            checkConnected();
            throw new IOException("not implemented");
        }
    }

    class KJASInputStream extends InputStream {
        private byte [] buf = null;
        private int bufpos = 0;
        private boolean eof = false;

        KJASInputStream() {
        }
        private boolean getData() throws IOException {
            if (eof)
                return false;
            checkConnected();
            if (haveError()) {
                disconnect();
                throw new IOException("i/o error " + errorcode);
            }
            if (buf != null && bufpos < buf.length)
                return true;
            synchronized (jobs) {
                if (data.size() > 0) {
                    buf = (byte []) data.removeFirst();
                    bufpos = 0;
                    return true;
                }
            }
            if (finished) {
                eof = true;
                synchronized (jobs) {
                    jobs.remove(jobid);
                }
                return false;
            }
            thread = Thread.currentThread();
            try {
                Thread.currentThread().sleep(10000);
            } catch (InterruptedException ie) {
                thread = null;
                return getData();
            }
            thread = null;
            disconnect();
            throw new IOException("timeout");
        }
        public int read() throws IOException {
            if (getData())
                return 0x00ff & buf[bufpos++];
            return -1;
        }
        public int read(byte[] b, int off, int len) throws IOException {
            if (!getData())
                return -1;
            int nr = buf.length - bufpos;
            if (nr > len)
                nr = len;
            System.arraycopy(buf, bufpos, b, off, nr);
            bufpos += nr;
            return nr;
        }
        public int read(byte[] b) throws IOException {
            return read(b, 0, b.length);
        }
        public int available() throws IOException {
            if (eof)
                return 0;
            checkConnected();
            return buf == null ? 0 : buf.length - bufpos;
        }
        public boolean markSupported() {
            return false;
        }
        public void close() throws IOException {
            checkConnected();
            disconnect();
        }
    }

    private KJASOutputStream out = null;
    private KJASInputStream in = null;

    KIOConnection(URL u) {
        url = u;
    }
    public void setData(int code, byte [] d) {
        // this method is synchronized on jobs in processCommand
        switch (code) {
            case FINISHED:
                finished = true;
                break;
            case DATA:
                if (d.length > 0)
                    data.addLast(d);
                Main.debug ("XXXXXXX DATA " + data.size());
                break;
            case ERRORCODE:
                String codestr = new String(d);
                errorcode = Integer.parseInt(codestr);
                Main.debug ("ERRORECODE " + errorcode);
                break;
        }
    }
    synchronized void connect(boolean doInput) throws IOException {
        Main.debug ("XXXXXX connect " + url);
        if (connected)
            throw new IOException("already connected");
        errorcode = 0;
        synchronized (jobs) {
            jobid = String.valueOf(id++);
            thread = Thread.currentThread();
            jobs.put(jobid, this);
        }
        if (doInput)
            Main.protocol.sendGetURLDataCmd(jobid, url.toExternalForm());
        try {
            Thread.currentThread().sleep(20000);
        } catch (InterruptedException ie) {
            connected = true;
            if (doInput)
                in = new KJASInputStream();
            else
                out = new KJASOutputStream();
            if (!haveError()) {
                thread = null;
                return;
            }
        }
        synchronized (jobs) {
            jobs.remove(jobid);
        }
        thread = null;
        if (connected) {
            connected = false;
            Main.debug ("XXXXXXX connect error");
            throw new IOException("connection failed (not found)");
        }
        Main.debug ("XXXXXXX connect timeout");
        throw new IOException("connection failed (timeout)");
    }
    void disconnect() {
        (new Exception()).printStackTrace();
        if (!connected)
            return;
        synchronized (jobs) {
            jobs.remove(jobid);
        }
        connected = false;
        out = null;
        in = null;
    }
    InputStream getInputStream() throws IOException {
        Main.debug ("XXXXXXX getInputStream " + url);
        //(new Exception()).printStackTrace();
        if (!connected)
            connect(true);
        return in;
    }
    OutputStream getOutputStream() throws IOException {
        Main.debug ("XXXXXXX getOutputStream " + url);
        if (!connected)
            connect(false);
        return out;
    }
}

final class KIOHttpConnection extends KIOConnection
{
    final static int HEADERS = 3;
    final static int REDIRECT = 4;
    final static int MIMETYPE = 5;

    Vector headers = new Vector();
    Hashtable headersmap = new Hashtable();

    KIOHttpConnection(URL u) {
        super(u);
    }
    protected boolean haveError() {
        return errorcode >= 400;
    }
    public void setData(int code, byte [] d) {
        // this method is synchronized on jobs in processCommand
        switch (code) {
            case HEADERS:
                StringTokenizer tokenizer = new StringTokenizer(new String(d), "\n");
                while (tokenizer.hasMoreTokens()) {
                    String token = tokenizer.nextToken();
                    int pos = token.indexOf(":");
                    String [] entry = {
                        token.substring(0, pos > -1 ? pos : token.length()).toLowerCase(), token.substring(pos > -1 ? pos+1: token.length())
                    };
                    headers.add(entry);
                    headersmap.put(entry[0], entry[1]);
                    Main.debug ("XXXXXXX header " + entry[0] + "=" + entry[1]);
                }
            default:
                super.setData(code, d);
        }
        
    }
}

final class KIOFtpConnection extends KIOConnection
{
    KIOFtpConnection(URL u) {
        super(u);
    }
}

final class KJASHttpURLConnection extends HttpURLConnection
{
    private KIOHttpConnection kioconnection;

    KJASHttpURLConnection(URL u) {
        super(u);
        kioconnection = new KIOHttpConnection(u);
    }
    public Map getHeaderFields() {
        Main.debug ("XXXXXXX getHeaderFields");
        return kioconnection.headersmap;
    }
    public String getHeaderField(String name) {
        Main.debug ("XXXXXXX getHeaderField " + name);
        return (String) kioconnection.headersmap.get(name);
    }
    public String getHeaderField(int n) {
        if (n >= kioconnection.headersmap.size())
            return null;
        String [] entry = (String []) kioconnection.headers.get(n);
        String line = entry[0];
        if (entry[1].length() > 0)
            line += ":" + entry[1];
        Main.debug ("XXXXXXX getHeaderField " + line);
        return line;
    }
    public String getHeaderFieldKey(int n) {
        Main.debug ("XXXXXXX getHeaderFieldKey " + n);
        if (n >= kioconnection.headersmap.size())
            return null;
        return ((String []) kioconnection.headers.get(n))[0];
    }
    public boolean usingProxy() {
        return false; // FIXME
    }
    public synchronized void connect() throws IOException {
        kioconnection.connect(doInput);
        Main.debug ("XXXXXXX connect responsecode=" + getResponseCode());
        String token = getHeaderField(0);
        do {
            if (!token.startsWith("HTTP/1.")) break;
            int spos = token.indexOf(' ');
            if (spos < 0) break;
            int epos = token.indexOf(' ', spos + 1);
            if (epos < 0) break;
            responseCode = Integer.parseInt(token.substring(spos+1, epos));
            responseMessage = token.substring(epos);
        } while (false);
    }
    public void disconnect() {
        kioconnection.disconnect();
    }
    public InputStream getInputStream() throws IOException {
        return kioconnection.getInputStream();
    }
    public OutputStream getOutputStream() throws IOException {
        return kioconnection.getOutputStream();
    }
}

final class KJASFtpURLConnection extends URLConnection
{
    private KIOFtpConnection kioconnection;

    KJASFtpURLConnection(URL u) {
        super(u);
        kioconnection = new KIOFtpConnection(u);
    }
    public boolean usingProxy() {
        return false; // FIXME
    }
    public synchronized void connect() throws IOException {
        kioconnection.connect(doInput);
    }
    public void disconnect() {
        kioconnection.disconnect();
    }
    public InputStream getInputStream() throws IOException {
        return kioconnection.getInputStream();
    }
    public OutputStream getOutputStream() throws IOException {
        return kioconnection.getOutputStream();
    }
}


final class KJASHttpURLStreamHandler extends URLStreamHandler
{
    KJASHttpURLStreamHandler() {
    }
    protected URLConnection openConnection(URL u) throws IOException {
        Main.debug ("XXXXXXX openConnection " + u);
        return new KJASHttpURLConnection(u);
    }
    protected int getDefaultPort() {
        return 80;
    }
}

final class KJASFtpURLStreamHandler extends URLStreamHandler
{
    KJASFtpURLStreamHandler() {
    }
    protected URLConnection openConnection(URL u) throws IOException {
        Main.debug ("XXXXXXX KJASFtpURLStreamHandler.openConnection " + u);
        return new KJASFtpURLConnection(u);
    }
    protected int getDefaultPort() {
        return 21;
    }
}

public final class KJASURLStreamHandlerFactory 
    implements URLStreamHandlerFactory
{
    public URLStreamHandler createURLStreamHandler(String protocol) {
        Main.debug ("XXXXXXX createURLStreamHandler " + protocol);
        if (protocol.equals("http"))
            return new KJASHttpURLStreamHandler();
        else if (protocol.equals("ftp"))
            return new KJASFtpURLStreamHandler();
        return null;
    }
}


More information about the kfm-devel mailing list