有没有简单的方法来预处理和重定向 GET 请求? [英] Is there any easy way to preprocess and redirect GET requests?

查看:16
本文介绍了有没有简单的方法来预处理和重定向 GET 请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找最佳实践答案.我想对 GET 请求做一些预处理.所以例如如果不允许用户查看该页面,则将他重定向到另一个页面.但我不想使用普通的 servlet 过滤器,因为我想在 faces-config.xml 中表达这种行为.这可能吗?怎么称呼,怎么做?

I'm looking for a best practise answer. I want to do some preprocessing for GET requests. So e.g. if the user is not allowed to see the page, redirect him to another page. But I don't want to use normal servlet filter, because I would like to express this behavior in the faces-config.xml. Is this possible and how is that called, how can it be done?

我可以定义一些过滤器 bean,它也返回一个字符串,告诉 faces-config.xml 下一步去哪里吗?

Can I define some Filter bean that also returns a String telling the faces-config.xml where to go next?

我用谷歌搜索了这个,但只找到了普通过滤器.如果我使用过滤器,一个 @WebFilter 可以同时是一个 @ManagedBean 吗?还是那种风格不好?

I googled for this but only hit on the normal filters. If I use filters, can a @WebFilter be a @ManagedBean at the same time? Or is that bad style?

推荐答案

如果您正在 JSF 之上进行 HTTP 请求身份验证,那么 servlet 过滤器确实是最好的方法.JSF 是公正"的一个 MVC 框架,JSF API 中没有指定任何内容来过滤传入的 HTTP 请求以检查用户身份验证.对于普通的 GET 请求,JSF 托管 bean 通常仅在 HTTP 响应即将创建和发送时才构造,或者可能已经提交.这是无法从托管 bean 内部控制的.如果响应已经提交,您将无法再更改(重定向)它.身份验证和更改请求/响应确实需要在响应即将发送之前完成.

If you're homegrowing HTTP request authentication on top of JSF, then a servlet filter is really the best approach. JSF is "just" a MVC framework and nothing in the JSF API is been specified to filter incoming HTTP requests to check user authentication. On normal GET requests, a JSF managed bean is usually only constructed when the HTTP response is about to be created and sent, or maybe already is been committed. This is not controllable from inside the managed bean. If the response is already been committed, you would not be able anymore to change (redirect) it. Authentication and changing the request/response really needs to be done far before the response is about to be sent.

如果您不是家庭身份验证,那么您可以使用 Java EE 提供的容器管理的身份验证,它由 <security-constraint>web.xml 中的条目声明.xml.请注意,这也与 JSF 分离,但它至少可以使您免于自己开发 servlet 过滤器和托管 bean.

If you were not homegrowing authentication, then you could have used the Java EE provided container managed authentication for this which is to be declared by <security-constraint> entries in web.xml. Note that this is also decoupled from JSF, but it at least saves you from homegrowing a servlet filter and a managed bean.

一般的方法是将受限制的页面分组在某个 URL 模式之后,例如 /app/*/private/*/secured/* 等,并利用 JSF 将会话范围 bean 存储为 HttpSession 属性这一事实.想象一下,您有一个 JSF 会话范围托管 bean UserManager 保存登录用户,然后您可以按如下方式检查它:

The general approach is to group the restricted pages behind a certain URL pattern like /app/*, /private/*, /secured/*, etc and to take the advantage of the fact that JSF stores session scoped beans as HttpSession attributes. Imagine that you've a JSF session scoped managed bean UserManager which holds the logged-in user, then you could check for it as follows:

@WebFilter(urlPatterns={"/app/*"})
public class AuthenticationFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        UserManager userManager = (session != null) ? (UserManager) session.getAttribute("userManager") : null;

        if (userManager == null || !userManager.isLoggedIn()) {
            response.sendRedirect(request.getContextPath() + "/login.xhtml"); // No logged-in user found, so redirect to login page.
        } else {
            chain.doFilter(req, res); // Logged-in user found, so just continue request.
        }
    }

    // ...
}

如果您使用的是 JSF 2.2+,还有另一种方法可以在响应发送之前控制响应.您可以使用 <代码>.将以下内容放在您的视图中:

If you're using JSF 2.2+, there's another way to control the response right before it is been sent. You can make use of the <f:viewAction>. Put the following somewhere in your view:

<f:metadata>
    <f:viewAction action="#{authenticator.check}" />
</f:metadata>

@Named
@RequestScoped // Scope doesn't matter actually. The listener will always be called on every request.
public class Authenticator {

    public String check() {
        if (authenticated) {
            return null;
        }
        else {
            return "login?faces-redirect=true";
        }
    }

    // ...
}

这保证在呈现响应之前被触发.否则,当您在例如@PostConstruct,那么当响应已经部分呈现(并提交)时第一次创建 bean 时,您可能会面临 java.lang.IllegalStateException: response already commit).

This is guaranteed to be fired before the response is to be rendered. Otherwise when you do the job in e.g. @PostConstruct, then you may risk java.lang.IllegalStateException: response already committed when the bean is created for the first time when the response has already partially been rendered (and committed).

我只是不认为它是最好的"练习处理 HTTP 身份验证.它使它与 JSF 耦合得太紧.您真的应该继续使用 servlet 过滤器.但用于其他目的,可能没问题.

I only wouldn't consider it to be a "best" practice when it comes to handling HTTP authentication. It makes it too tight coupled into JSF. You should really keep using a servlet filter. But for other purposes, it may be fine.

这篇关于有没有简单的方法来预处理和重定向 GET 请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆