【问题标题】:How to seam-authenticate through Servlet如何通过 Servlet 进行无缝身份验证
【发布时间】:2012-08-28 11:31:49
【问题描述】:

我知道这不是应有的方式,而且完全错误,但命令就是命令,我需要执行以下操作: 用户使用参数上的 accesskey 访问 servlet,如下所示:

http://myhost/my_app/servlet?accesskey=XXXXX

servlet 然后获取密钥并使用它在 seam 上对用户进行身份验证,这可能吗?到目前为止,我无法做到这一点

【问题讨论】:

    标签: java seam jsf-1.2 jboss-4.2.x


    【解决方案1】:

    根据您的问题,不清楚您是否需要创建自定义 servlet,或者您只需要根据请求参数进行登录。主要区别在于自定义 servlet 不会被 Seam 拦截,除非您手动启动 Seam 生命周期,否则您无法使用组件(如 Trind 所述,您需要使用 LifeCycle.beginCall()LifeCycle.endCall() 才能在以下情况下使用 Seam 组件)从外面打电话SeamFilter)。除此之外,这两种解决方案的工作方式类似。

    创建一个将处理身份验证的组件:

    @Name("myAuthenticator")
    public class MyAuthenticator implements Serializable {
    
        // Seam's identity component
        @In private transient Identity identity;
    
        // When logged in, the user needs to have some roles, usually
        // you assign these dynamically based on user name, type, etc., here
        // I just initialize it to a fixed list of roles
        ArrayList<String> roles = new ArrayList<String>(Arrays.toList(
                new String[] { "base", "admin" }));
    
        // Access key (getters and setters omitted but are necessary)
        private String accessKey;
    
        public String doAuth() {
            // Check accessKey validity (against an SSO service or 
            // in your DB or whatever), here we do a trivial check.
            boolean userCanAccess = "ADMINKEY".equals(accessKey);
    
            if (userCanAccess) {
                identity.acceptExternallyAuthenticatedPrincipal(
                        new SimplePrincipal("username"));
    
                // Assign user roles
                for (String role : roles) {
                    identity.addRole(role);
                }
                return "ok";
            }
            return "ko";
        }
    }
    

    现在创建一个登录页面描述符,它将通过参数处理登录(比如externalLogin.page.xml,你不需要为此创建一个.xhtml页面):

    <page>
        <!-- this sets the accessKey variable with the query parameter -->
        <param name="accessKey" value="#{myAuthenticator.accessKey}" />
    
        <!-- this invokes our authentication action -->
        <action execute="#{myAuthenticator.doAuth}" />
    
        <!-- navigation rules, these determine what to do if auth is ok or fails -->
        <navigation from-action="#{myAuthenticator.doAuth}">
            <rule if-outcome="ko">
                <redirect view-id="/error.xhtml">
                    <message severity="ERROR">Invalid Authentication Key</message>
                </redirect>
            </rule>
            <rule if-outcome="ok">
                <redirect view-id="/home.xhtml">
                    <message severity="INFO">Welcome!</message>
                </redirect>
            </rule>
        </navigation>
    </page>
    

    现在要执行登录,您可以使用该页面,如下所示:

    http://localhost:8080/yourapp/externalLogin.seam?accessKey=XXXXXXXX
    

    如果您需要使用自定义 servlet(不太可能,但无论如何),上述组件不会更改,只需从 servlet 中调用它,如下所示:

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // Start Seam lifecycle
        LifeCycle.beginCall();
        // Get an instance of the authenticator component from Seam
        MyAuthenticator auth = Component.getInstance("myAuthenticator");
        // Set access key in component and perform auth
        auth.setAccessKey(req.getParameter("accessKey"));
        String result = auth.doAuth();
        // End Seam lifecycle, no more component calls are needed.
        LifeCycle.endCall();
    
        // Do something here with the result
        if ("ok".equals(result)) {
            resp.sendRedirect(...);
        }
    }
    

    【讨论】:

    • 如果我选择将现有的身份验证方法与您展示的第一种方式一起使用,它会起作用吗?我正在使用基于教程的身份验证器:http://pastebin.com/mZHNT8kP
    • 简短的回答是否定的,“标准”身份验证器实际上并不执行身份验证,它只是返回一个布尔值,说明用户是否应该进行身份验证。我给你的验证码执行实际的验证(identity.acceptExternallyAuthenticatedPrincipal() 调用)。
    【解决方案2】:

    您的 servlet 中的这段代码应该使您能够访问您的接缝组件。

    Lifecycle.beginCall();
    
    Authenticator authenticator = (Authenticator)Component.getInstance("authenticator");
    
    LifeCycle.endCall();
    

    【讨论】:

    • LifeCycle 来自哪个软件包?唯一具有该类的包是 org.jboss.seam.contexts、javax.faces.lifecycle 和 org.hibernate.classic,它们都没有您上面使用的 Begin 方法,您在代码中使用了哪个包?另外,我应该如何使用您的代码进行身份验证?我已经从 GET 中获得了参数,但是我应该如何将它传递给 Authenticator 密码变量和 authenticate()?
    • Trind 你能回答吗?
    • 抱歉,begincCall 不只是开始
    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多