Вход пользователя с JSF 2.0
Я пытаюсь - с JSF 2.0 - реализовать аккуратным способом управление логином/записью/выводом. Поскольку традиционный способ <form action="j_security_check" ...
не обладает гибкостью, я решил пойти по другому пути, но я нашел проблему.
Декларативная безопасность правильно устанавливается как на сервере приложений через <security-domain>
, так и в web.xml через <security-constraint>
, <login-config>
и <form-login-page>
.
Страница входа:
<h:form id="loginForm">
<h:panelGrid columns="2" cellspacing="5">
<h:outputText value="Username" />
<h:inputText value="#{loginBean.username}" />
<h:outputText value="Password:" />
<h:inputText value="#{loginBean.password}" />
<h:outputLabel value=""/>
<h:commandButton value="Login" action="#{loginBean.login}" />
</h:panelGrid>
</h:form>
И простой LoginBean # login():
public String login( )
{
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance( ).getExternalContext( ).getRequest( );
try {
request.login( username, password );
}
catch ( ServletException e ) {
FacesContext.getCurrentInstance().addMessage( "Unknown login...
return null;
}
return "i_dont_know_where_you_were_going";
}
Все работает нормально, но после успешного входа я не знаю, как перенаправить пользователя в исходный запрос. Поскольку страница входа автоматически вставлена между запросом клиента и "любым" защищенным ресурсом, мне нужен способ понять, где перенаправить действие. request.getRequestURL( )
не помогает, возможно, из-за RequestDispatcher#forward()
(который перезаписывает запрос url). Считаете ли вы, что это подходящий способ управления процессом входа в систему? Если да, то какой-нибудь намек на проблему?
Спасибо большое!
Ответы
Ответ 1
Добавьте в свою учетную запись что-то вроде следующей строки. Он сохраняет запрашиваемую страницу во время входа в систему.
<f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" />
Затем введите запрошенный uri в свой логин bean.
FacesContext context = FacesContext.getCurrentInstance();
String redirect = context.getExternalContext().getRequestParameterMap().get("redirect");
Добавьте ?faces-redirect=true
в строку и верните ее.
Ответ 2
Вышеупомянутый ответ работал отлично, просто указывая на неосторожного. f: имя параметра должно быть внутри чего-то вроде commandButton...
<p:commandButton value="Entrar" icon="ui-icon-disk" action="#{userMB.login}" update="avisos,mensagens" ajax="false">
<f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" />
</ p: commandButton>
Ответ 3
Кажется, что это работает только при размещении между кнопкой (Mojarra 2.2, Glassfish 4). Вам понадобятся эти два тега <f:param
javax.servlet.forward.request_uri
и javax.servlet.forward.query_string
, чтобы обеспечить точную переадресацию на все типы URL (с или без строк запроса). Убедитесь, что у вас есть что-то похожее на фрагмент ниже на вашей странице входа, то есть на страницу, указанную в вашем web.xml
для входа
(<form-login-page>/login.xhtml</form-login-page>
).
<h:commandButton value="Login" action="#{securityController.login()}">
<f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" />
<f:param name="query_string" value="#{requestScope['javax.servlet.forward.query_string']}" />
</h:commandButton>
Затем вы можете получить оба параметра в резервной копии bean после отправки формы, как показано ниже
public String login() {
try {
String nextPage = "/index.xhtml"; // have a default value in case the user goes to login page directly.
ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
Map<String, String> map = ctx.getRequestParameterMap();
String redirect = map.get("redirect");
String queryString = map.get("query_string");
HttpServletRequest request = (HttpServletRequest) ctx.getRequest();
request.login(this.username, this.password);
// here login is successful otherwise it would've thrown exception
// now let check the kind of URL our user was going to
if (redirect != null && !redirect.isEmpty()) { // if redirect is null, return the default page
// please use faces-redirect = true to ensure URL change in the browser
if (queryString != null) {
nextPage = redirect + "?" + queryString + "&faces-redirect=true";
} else { // there is no query string, nextPage = redirect
nextPage = redirect + "&faces-redirect=true";
}
// Caveat: You may not need the next lines of code.
// I discovered that the `redirect` string has my context path
// value in it and so it was'nt redirecting. Remove the context path
if (nextPage.contains(request.getContextPath())) {
nextPage = nextPage.substring(request.getContextPath().length());
}
}
} catch (ServletException ex) {
Logger.getLogger(SecurityController.class.getName()).log(Level.SEVERE, null, ex);
// invalid username or password
return "/login.xhtml?failed=true"; // or login error page
}
return nextPage;
}
Надеюсь, это поможет кому-то.