本文介绍了我如何以编程方式调用一个servlet内等认证j_security_check会做的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有 j_securtiy_check 基于Web表单的登录认证工作。我们希望通过编程登录身份验证来改变它。什么是有一个servlet验证传递给它的用户名和密码的正确方法?该servlet显然是不受保护的。

我们一直在尝试这样的server.xml领域:

 <境界的className =org.apache.catalina.realm.DataSourceRealm
    了dataSourceName =UserDatabase
    为UserTable =APP_USERuserNameCol =LOGIN_NAMEuserCredCol =password_value
    userRoleTable =user_permroleNameCol =PERMISSION_NAME
    allRolesMode =authOnly消化=MD5
/>

这样做的原因,是我们必须发送登录信息到未受保护的loginServlet一个Java Webstart的客户端。这个servlet验证目前针对JOSSO单点登录服务,但我想删除此和使用简单的tomcat7认证对于初学者。然后最终迁移到OpenAM。如果我能编程生成JSSESSIONIDSSO值,塞进一个cookie这一点。

这是一些code,我发现。这是调用验证的正确方法?

  ApplicationContextFacade ACF =(ApplicationContextFacade)this.getServletContext();现场privateField = ApplicationContextFacade.class.getDeclaredField(上下文);
privateField.setAccessible(真);
ApplicationContext的appContext =(ApplicationContext的)privateField.get(ACF);
现场privateField2 = ApplicationContext.class.getDeclaredField(上下文);
privateField2.setAccessible(真);
StandardContext stdContext =(StandardContext)privateField2.get(appContext);
境界境界= stdContext.getRealm();主要主体= realm.authenticate(loginBean.getUsername(),loginBean.getPassword());
如果(本金== NULL)
{
   返回0;
}
的GenericPrincipal的GenericPrincipal =(的GenericPrincipal)负责人;的System.out.println(的GenericPrincipal =+ genericPrincipal.toString());


解决方案

我注意到,这已不再是最新的。最终的解决方案是使用Java SDK的OpenAM提供。

这是一个起点:http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/dev-guide/index/chap-jdk.html

1)添加的所有附带此SDK到你的Web应用程序的jar文件。
2)改变你的servlet(或重客户端)具有下列code:

 私人无效addLoginCallbackMessage(LoginCredentialsBean loginBean,回调[]回调)
        抛出UnsupportedCallbackException在
{
    INT I = 0;
    尝试
    {
        对于(i = 0; I< callbacks.length;我++)
        {
            如果(回调[I]的instanceof TextOutputCallback并将)
            {
                handleTextOutputCallback((TextOutputCallback并将)回调[I]);
            }
            否则,如果(回调[I]的instanceof的NameCallback)
            {
                handleNameCallback(loginBean.getUsername(),(NameCallback来)回调[I]);
            }
            否则,如果(回调[I]的instanceof PasswordCallback)
            {
                handlePasswordCallback(loginBean.getPassword(),(PasswordCallback)回调[I]);
            }
            否则,如果(回调[I]的TextInputCallback的instanceof)
            {
                handleTextInputCallback((的TextInputCallback)回调[I]);
            }
            否则,如果(回调[I]的instanceof ChoiceCallback)
            {
                handleChoiceCallback((ChoiceCallback)回调[I]);
            }
        }
    }
    赶上(IOException异常E)
    {
        e.printStackTrace();
        抛出新UnsupportedCallbackException在(回调[I],e.getMessage());
    }
}私人无效handleTextOutputCallback(TextOutputCallback并将TOC)
{
    的System.out.println(得到TextOutputCallback并将);
    //根据指定类型显示信息    开关(toc.getMessageType())
    {
    案例TextOutputCallback.INFORMATION:
        的System.out.println(toc.getMessage());
        打破;
    案例TextOutputCallback.ERROR:
        的System.out.println(错误:+ toc.getMessage());
        打破;
    案例TextOutputCallback.WARNING:
        的System.out.println(警告:+ toc.getMessage());
        打破;
    默认:
        的System.out.println(不支持的消息类型:+
                toc.getMessageType());
    }
}私人无效handleNameCallback(字符串名称,NameCallback来NC)
        抛出IOException异常
{
    nc.setName(名);
}私人无效handleTextInputCallback(TIC的TextInputCallback)
        抛出IOException异常
{
    //不支持服务器端
    //提示文字输入
}私人无效handlePasswordCallback(字符串密码,PasswordCallback PC)
        抛出IOException异常
{
    //提示输入敏感信息的用户    pc.setPassword(password.toCharArray());
}私人无效handleChoiceCallback(ChoiceCallback CC)
        抛出IOException异常
{
    //不支持服务器端    //忽略所提供的设置defaultValue
    / *
    System.out.print(cc.getPrompt());    的String [] = strChoices cc.getChoices();
    对于(INT J = 0; J< strChoices.length; J ++)
    {
        System.out.print(选择[+ J +]:+ strChoices [J]);
    }
    System.out.flush();
    cc.setSelectedIndex(的Integer.parseInt((新的BufferedReader
            (新的InputStreamReader(System.in)))的readLine()))。
    * /
}
私人无效doLogin()
{
    // ...许多其他的逻辑在这里    // TODO:这一个是为OpenAM做成模块,此
    如果(_useOpenAM)
    {
        字符串ORGNAME =/;
        字符串MODULENAME =数据存储;
        字符串的区域设置=EN_US;        AuthContext LC =新AuthContext(ORGNAME);
        AuthContext.IndexType INDEXTYPE = AuthContext.IndexType.MODULE_INSTANCE;
        lc.login(INDEXTYPE,MODULENAME,环境);        布尔成功= FALSE;
        回调[]回调= NULL;        //从模块所需的信息
        而(lc.hasMoreRequirements())
        {
            回调= lc.getRequirements();
            如果(回调!= NULL)
            {
                addLoginCallbackMessage(loginBean,回调);
                lc.submitRequirements(回调);
            }
        }        如果(lc.getStatus()== AuthContext.Status.SUCCESS)
        {
            尝试
            {
                的System.out.println(登录成功);
                openAMSessionId = lc.getAuthIdentifier();
                的System.out.println(lc.getAuthIdentifier()=+ openAMSessionId);
                的System.out.println(lc.getSuccessURL()=+ lc.getSuccessURL());
                的System.out.println(。lc.getSSOToken()getAuthLevel()=+ lc.getSSOToken()getAuthLevel());
                的System.out.println(。lc.getSSOToken()getAuthType()=+ lc.getSSOToken()getAuthType());
                的System.out.println(。lc.getSSOToken()的gethostname()=+ lc.getSSOToken()的gethostname());
                的System.out.println(。lc.getSSOToken()getIdleTime()=+ lc.getSSOToken()getIdleTime());
                的System.out.println(。lc.getSSOToken()getMaxIdleTime()=+ lc.getSSOToken()getMaxIdleTime());
                的System.out.println(。lc.getSSOToken()getMaxSessionTime()=+ lc.getSSOToken()getMaxSessionTime());
                的System.out.println(。lc.getSSOToken()getTimeLeft()=+ lc.getSSOToken()getTimeLeft());
                的System.out.println(。lc.getSSOToken()getIPAddress()=+ lc.getSSOToken()getIPAddress());
                的System.out.println(。lc.getSSOToken()getTokenID()=+ lc.getSSOToken()getTokenID()的toString());
                的System.out.println(。lc.getSSOToken()getPrincipal()=+ lc.getSSOToken()getPrincipal()的toString());
            }
            赶上(例外五)
            {
                e.printStackTrace();
            }            成功= TRUE;
        }
        否则如果(lc.getStatus()== AuthContext.Status.FAILED)
        {
            的System.out.println(登录失败。);
        }
        其他
        {
            的System.out.println(未知状态:+ lc.getStatus());
        }        的System.out.println(OpenAM登录成功=+成功);
    }
}

从上面的code而言,重要的是可变openAMSessionId。这最终有会话ID的新OpenAM单点登录,你可以四处传递给所有的受保护的客户端应用程序,使用户不会被质疑登录。

我希望这有助于。

-dklotz

We have the web based form login authentication with j_securtiy_check working. We'd like to change it by programmatic login authentication. What is the proper way of having a servlet authenticate a user name and password passed to it? The servlet is obviously unprotected.

We have been experimenting with this server.xml Realm:

<Realm  className="org.apache.catalina.realm.DataSourceRealm"
    dataSourceName="UserDatabase"
    userTable="app_user" userNameCol="login_name" userCredCol="password_value"
    userRoleTable="user_perm" roleNameCol="permission_name"
    allRolesMode="authOnly" digest="MD5"
/>

The reason for this, is that we have a java webstart client that sends login information to an unprotected loginServlet. This servlet currently authenticates against a JOSSO single sign-on service but I wish to remove this and use simple tomcat7 authentication for starters. Then eventually migrate to OpenAM. If I could programmatically generate the JSSESSIONIDSSO value and stuff this into a cookie.

This is some code that I found. Is this the right way to invoke authentication?

ApplicationContextFacade acf = (ApplicationContextFacade) this.getServletContext();

Field privateField = ApplicationContextFacade.class.getDeclaredField("context");  
privateField.setAccessible(true);  
ApplicationContext appContext = (ApplicationContext) privateField.get(acf);  
Field privateField2 = ApplicationContext.class.getDeclaredField("context");  
privateField2.setAccessible(true);  
StandardContext stdContext = (StandardContext) privateField2.get(appContext);  
Realm realm = stdContext.getRealm();  

Principal principal = realm.authenticate(loginBean.getUsername(), loginBean.getPassword());  
if (principal == null)
{
   return 0;
}
GenericPrincipal genericPrincipal = (GenericPrincipal) principal;

System.out.println ("genericPrincipal=" + genericPrincipal.toString());
解决方案

I noticed that this is no longer up to date. The final solution was to use the Java SDK that OpenAM provides.

This is the starting point: http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/dev-guide/index/chap-jdk.html

1) add all of the jar files that come with this SDK to your web application. 2) Change your servlet (or heavy client) to have the following code:

    private void addLoginCallbackMessage(LoginCredentialsBean loginBean, Callback [] callbacks)
        throws UnsupportedCallbackException
{
    int i = 0;
    try
    {
        for (i = 0; i < callbacks.length; i++)
        {
            if (callbacks[i] instanceof TextOutputCallback)
            {
                handleTextOutputCallback((TextOutputCallback) callbacks[i]);
            }
            else if (callbacks[i] instanceof NameCallback)
            {
                handleNameCallback(loginBean.getUsername(), (NameCallback) callbacks[i]);
            }
            else if (callbacks[i] instanceof PasswordCallback)
            {
                handlePasswordCallback(loginBean.getPassword(), (PasswordCallback) callbacks[i]);
            }
            else if (callbacks[i] instanceof TextInputCallback)
            {
                handleTextInputCallback((TextInputCallback) callbacks[i]);
            }
            else if (callbacks[i] instanceof ChoiceCallback)
            {
                handleChoiceCallback((ChoiceCallback) callbacks[i]);
            }
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
        throw new UnsupportedCallbackException(callbacks[i], e.getMessage());
    }
}

private void handleTextOutputCallback(TextOutputCallback toc)
{
    System.out.println("Got TextOutputCallback");
    // display the message according to the specified type

    switch (toc.getMessageType())
    {
    case TextOutputCallback.INFORMATION:
        System.out.println(toc.getMessage());
        break;
    case TextOutputCallback.ERROR:
        System.out.println("ERROR: " + toc.getMessage());
        break;
    case TextOutputCallback.WARNING:
        System.out.println("WARNING: " + toc.getMessage());
        break;
    default:
        System.out.println("Unsupported message type: " +
                toc.getMessageType());
    }
}

private void handleNameCallback(String name, NameCallback nc)
        throws IOException
{
    nc.setName(name);
}

private void handleTextInputCallback(TextInputCallback tic)
        throws IOException
{
    // not supported for server side
    // prompt for text input
}

private void handlePasswordCallback(String password, PasswordCallback pc)
        throws IOException
{
    // prompt the user for sensitive information

    pc.setPassword(password.toCharArray());
}

private void handleChoiceCallback(ChoiceCallback cc)
        throws IOException
{
    // not supported for server side

    // ignore the provided defaultValue
    /*        
    System.out.print(cc.getPrompt());

    String [] strChoices = cc.getChoices();
    for (int j = 0; j < strChoices.length; j++)
    {
        System.out.print("choice[" + j + "] : " + strChoices[j]);
    }
    System.out.flush();
    cc.setSelectedIndex(Integer.parseInt((new BufferedReader
            (new InputStreamReader(System.in))).readLine()));
    */
}


private void doLogin ()
{
    // ... lots of other logic here

    // TODO: Make this into modules with this one being for OpenAM
    if (_useOpenAM)
    {
        String orgName = "/";
        String moduleName = "DataStore";
        String locale = "en_US";

        AuthContext lc = new AuthContext(orgName);
        AuthContext.IndexType indexType = AuthContext.IndexType.MODULE_INSTANCE;
        lc.login(indexType, moduleName, locale);

        boolean succeed = false;
        Callback [] callbacks = null;

        // get information requested from module
        while (lc.hasMoreRequirements())
        {
            callbacks = lc.getRequirements();
            if (callbacks != null)
            {
                addLoginCallbackMessage(loginBean, callbacks);
                lc.submitRequirements(callbacks);
            }
        }

        if (lc.getStatus() == AuthContext.Status.SUCCESS)
        {
            try
            {
                System.out.println("Login succeeded.");
                openAMSessionId = lc.getAuthIdentifier();
                System.out.println("lc.getAuthIdentifier()=" + openAMSessionId);
                System.out.println("lc.getSuccessURL()=" + lc.getSuccessURL());
                System.out.println("lc.getSSOToken().getAuthLevel()=" + lc.getSSOToken().getAuthLevel());
                System.out.println("lc.getSSOToken().getAuthType()=" + lc.getSSOToken().getAuthType());
                System.out.println("lc.getSSOToken().getHostName()=" + lc.getSSOToken().getHostName());
                System.out.println("lc.getSSOToken().getIdleTime()=" + lc.getSSOToken().getIdleTime());
                System.out.println("lc.getSSOToken().getMaxIdleTime()=" + lc.getSSOToken().getMaxIdleTime());
                System.out.println("lc.getSSOToken().getMaxSessionTime()=" + lc.getSSOToken().getMaxSessionTime());
                System.out.println("lc.getSSOToken().getTimeLeft()=" + lc.getSSOToken().getTimeLeft());
                System.out.println("lc.getSSOToken().getIPAddress()=" + lc.getSSOToken().getIPAddress());
                System.out.println("lc.getSSOToken().getTokenID()=" + lc.getSSOToken().getTokenID().toString());
                System.out.println("lc.getSSOToken().getPrincipal()=" + lc.getSSOToken().getPrincipal().toString());
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

            succeed = true;
        }
        else if (lc.getStatus() == AuthContext.Status.FAILED)
        {
            System.out.println("Login failed.");
        }
        else
        {
            System.out.println("Unknown status: " + lc.getStatus());
        }

        System.out.println( "OpenAM login success=" + succeed);
    }
}

The important thing from the above code is the variable openAMSessionId . That ends up having the new OpenAM single sign on session id that you can pass around to all of your protected client applications so that the user doesn't get challenged for login.

I hope this helps.

-dklotz

这篇关于我如何以编程方式调用一个servlet内等认证j_security_check会做的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-14 20:36