登录后重定向不起作用(jsf-glassfish)

时间:2014-01-25 19:29:46

标签: java jsf glassfish

我在glassfish-jee / jsf-jpa场景中, 当我尝试访问我的一个ManagerBean中的受保护函数时(我不满足@RolesAllowed指定的要求),我会收到web.xml中配置的登录页面的提示。 登录后,我被重定向到通用主页(home.xhtml)。

因为我的函数返回void(它在数据库中执行某些业务)我希望被重定向到登录后的同一页面。

当我尝试访问受保护的页面时,重定向的东西工作得很完美,但是受保护的函数不返回任何东西似乎“我来自无处,我将无处可去”(originalURL为null,请参阅下面的代码详情)

我在StackOverflow上搜索了一整天,我已经阅读了很多答案,但没有一个有效,到目前为止这些都是我的代码行。

login.xhtml

   <h:form>
        <h:outputLabel for="username" value="Username" />
        <h:inputText id="username" value="#{LoginManagedBean.username}"
            required="true" />
        <h:message for="username" />
        <br />
        <h:outputLabel for="password" value="Password" />
        <h:inputSecret id="password" value="#{LoginManagedBean.password}"
            required="true" />
        <h:message for="password" />
        <br />
        <h:commandButton value="Login" action="#{LoginManagedBean.login}" />
        <h:messages globalOnly="true" />

    </h:form>

LoginManagedBean.java

   package userInterfaces;


 //imports

/**
 * Session Bean implementation class LoginManagedBean
 */
@ManagedBean(name="LoginManagedBean")
@ViewScoped

public class LoginManagedBean {
    //getters and setters

    private String username;


    private String password;
    private String originalURL;

    public LoginManagedBean() {
        // TODO Auto-generated constructor stub
    }

    @PostConstruct
    public void init() {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        originalURL = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
        String uri = ((HttpServletRequest) externalContext.getRequest()).getRequestURI();

        if (originalURL == null) {
            originalURL = externalContext.getRequestContextPath() + "/home.xhtml";
        } else {
            String originalQuery = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_QUERY_STRING);

            if (originalQuery != null) {
                originalURL += "?" + originalQuery;
            }
        }
    }

    public void login() throws IOException {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();

        try {
            request.login(username, password); 
            externalContext.redirect(originalURL);
        } catch (ServletException e) {
          context.addMessage(null, new FacesMessage("Unknown login"));
        }
    }
       public void logout() throws IOException {
            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
            externalContext.invalidateSession();
            externalContext.redirect(externalContext.getRequestContextPath() + "/login.xhtml");
        }

}

的web.xml

    <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>TravelDreamDynamicWeb</display-name>
  <welcome-file-list>
    <welcome-file>home.jsf</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
    <url-pattern>*.xhtml</url-pattern>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
  <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>/login.xhtml</form-login-page>
      <form-error-page>/loginError.xhtml</form-error-page>
    </form-login-config>
  </login-config>
  <error-page>
    <error-code>403</error-code>
    <location>/loginError.xhtml</location>
  </error-page>
  <error-page>
    <error-code>500</error-code>
    <location>/login.xhtml</location>
  </error-page>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Pagine Cliente</web-resource-name>
      <description></description>
      <url-pattern>/cliente/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>CLIENTE</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Pagine Impiegato</web-resource-name>
      <description></description>
      <url-pattern>/impiegato/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>IMPIEGATO</role-name>
    </auth-constraint>
  </security-constraint>
</web-app>

具体功能的实施(仅仅是为了知识,对不起它是意大利语和英语的混合物

@Override
@RolesAllowed({"CLIENTE"})
public void aggiungiACarrelloMgr(int idPacchetto) {
    String username=FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
    Query query=em.createQuery("SELECT u FROM UtenteRegistrato u WHERE u.username='"+username+"'");
    List<UtenteRegistrato> utente= query.getResultList();
    int idCarrello=utente.get(0).getIdCarrello();
    Carrello carrello=new Carrello(new CarrelloPK(idCarrello,idPacchetto));
    em.persist(carrello);
}

“VisualizzaPacchetti.xhtml”中的命令按钮(对未登录的用户可见)尝试调用受保护的函数(在启动javax.ejb.AccessLocalException后触发转发登录页面)

<h:commandButton action="#{PacchettoManagedBean.aggiungiACarrello(PacchettoManagedBean.pacchetti.get(statoPack.index).idPacchetto)}" value="+CARRELLO" />

感谢您的时间, 请告诉我,如果我在解释中遗漏了一些内容,并抱歉我的英文不好

的Massimo

2 个答案:

答案 0 :(得分:0)

Hi Massimo,欢迎使用Stack Overflow。我快速检查了你的代码,似乎你的LoginManagedBean是ViewScoped,这意味着它保持状态直到视图相同。在您的情况下,您正在请求login.xhtml,这可能与您的原始视图不同,因此LoginManagedBean的状态将丢失。

尝试使用@ViewScoped中的@SessionScoped更改LoginManagedBean

我不知道它是否适合您的逻辑,以防它不仅仅为登录相关的东西创建一个会话范围的bean,因为无论如何你都需要它。看看你的方法名称我假设你正在构建一个电子商务(我也是意大利语),所以你可能已经有了一个会话范围的bean。

答案 1 :(得分:0)

要解决我的问题,我使用了本页http://mrj4mes.blogspot.it/2013/04/how-to-redirect-to-original-page-after.html

中描述的自定义登录版本

注意,我不得不改变建议的

<f:view>
<ui:param name="originalURL" value="#{request.requestURI}?#{request.queryString}" />
<f:metadata>
<f:event rendered="#{not userSession.loggedIn}" type="preRenderView" listener="#{userSession.recordOriginalURL(originalURL)}" />
</f:metadata>
</f:view>

到这个

<f:view>
<f:metadata>
<ui:param name="originalURL" value="#{request.requestURI}?#{request.queryString}" />
<f:event rendered="#{not userSession.loggedIn}" type="preRenderView" listener="#{userSession.recordOriginalURL(originalURL)}" />
</f:metadata>
</f:view> 

希望这可以帮助有同样问题的人。祝你好运