redirect after authentication - spring-security

After I integrated spring security into vaadin there of course appeared a need to redirect user after successfull authentication.
I integrated spring security using two servlets - one for vaadin and another - for spring security.
Here my web.xml
<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/pmc-web-context.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>another-pmc-servlet</servlet-name>
<servlet-class>ru.xpoft.vaadin.SpringVaadinServlet</servlet-class>
<init-param>
<param-name>beanName</param-name>
<param-value>pmcVaadin</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>another-pmc-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<servlet>
<servlet-name>login-pmc-servlet</servlet-name>
<servlet-class>ru.xpoft.vaadin.SpringVaadinServlet</servlet-class>
<init-param>
<param-name>beanName</param-name>
<param-value>loginVaadin</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>login-pmc-servlet</servlet-name>
<url-pattern>/login/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
My security context looks like this
<http auto-config="true">
<intercept-url pattern="/*" access="ROLE_USER"/>
<form-login login-page="/login/" default-target-url="/*" authentication-failure-url="/login/?login_error=true"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="pass" authorities="ROLE_USER"/>
<user name="admin" password="admin" authorities="ROLE_ADMIN, ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
On my loginUI(bean name loginVaadin) page there is a login form
public class LoginForm extends Window {
private TextField login;
private TextField password;
private Button enter;
private HorizontalLayout buttonLayout;
private FormLayout formLayout;
private Image facebookIcon;
#Override
public void attach() {
setCaption(StringValues.LOGIN_FORM_CAPTION);
setSizeUndefined();
setResizable(false);
setModal(true);
setContent(createLayout());
super.attach();
}
private FormLayout createLayout() {
login = new TextField("Login");
password = new TextField("Password");
enter = new Button("Enter(close)");
final LoginUi ui = (LoginUi) LoginUi.getCurrent();
enter.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
String loginValue = login.getValue();
String passwordValue = password.getValue();
AuthenticationService authenticationService = ui.getAuthenticationService();
String result = authenticationService.authorize(loginValue, passwordValue);
if (StringUtils.isBlank(result)) {
LoginForm.this.close();
}
ui.getPage().setLocation("localhost:8080/pmc-web/");
}
});
buttonLayout = new HorizontalLayout();
String pathToFile = VaadinService.getCurrent().getBaseDirectory()
.getAbsolutePath() + "\\WEB-INF\\images\\facebook_icon.png";
FileResource resource = new FileResource(new File(pathToFile));
facebookIcon = new Image(null, resource);
facebookIcon.addClickListener(new MouseEvents.ClickListener() {
#Override
public void click(com.vaadin.event.MouseEvents.ClickEvent event) {
try {
ui.getPage().setLocation(ui.getAuthenticationService()
.redirect(ui.getProperty("oauth.application"), ui.getProperty("oauth.callback")));
} catch (Exception e) {
Notification.show(e.getMessage());
}
}
});
buttonLayout.addComponent(facebookIcon);
buttonLayout.addComponent(enter);
buttonLayout.setComponentAlignment(enter, Alignment.BOTTOM_LEFT);
formLayout = new FormLayout(login, password, buttonLayout);
formLayout.setComponentAlignment(buttonLayout, Alignment.BOTTOM_LEFT);
formLayout.setMargin(true);
return formLayout;
}
}
But how to make it redirect to required me vaadin page with all components(ui bean name pmcVaadin)? Because when I do like this - it's again being intercepted and it shows me loginform again.

First of all shorten and clean up your "createLayout" method. ;)
Try:
ui.getNavigator().navigateTo("pmc-web");

Related

Http Session is Null in AuthenticatedWebSession Wicket And Spring Security

Environment:
<wicket.version>7.7.0</wicket.version>
<spring.version>4.3.8.RELEASE</spring.version>
<springsecurity.version>4.2.3.RELEASE</springsecurity.version>
I have custom class from AuthenticatedWebSession like:
public class WicketSession extends AuthenticatedWebSession {
private static final Logger log = LoggerFactory.getLogger(WicketSession.class);
private static final long serialVersionUID = 1L;
private final HttpSession httpSession;
#SpringBean(name = "authenticationManager")
private AuthenticationManager authenticationManager;
public WicketSession(Request request) {
super(request);
this.httpSession = ((HttpServletRequest) request.getContainerRequest()).getSession();
log.debug("Got httpSession: {}", this.httpSession);
Injector.get().inject(this);
}
#Override
public boolean authenticate(String username, String password) {
try {
final Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
log.debug("Username '{}' is {} auth with authorities: {}",
username, auth.isAuthenticated(), auth.getAuthorities());
if (auth.isAuthenticated()) {
// the authentication object has to be stored in the SecurityContextHolder and in the HttpSession manually, so that the
// security context will be accessible in the next request
SecurityContextHolder.getContext().setAuthentication(auth);
httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
return true;
} else {
return false;
}
} catch (AuthenticationException e) {
log.warn("Failed login attempt due to exception!", e);
return false;
}
}
}
Spring Security Config like:
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
public SpringSecurityConfig() {
super(false);
}
#Override
#Bean
public UserDetailsService userDetailsService() {
final InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("admin").password("admin").roles("ADMIN").build());
manager.createUser(User.withUsername("rudi").password("rudi").roles("USER").build());
return manager;
}
#Bean(name = "authenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/user/**").authenticated()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/**").permitAll()
.and().formLogin().loginPage("/login")
.and().addFilter(new SecurityContextPersistenceFilter()).securityContext();
}
}
Spring Application Config like:
#PropertySource({"classpath:/META-INF/rcommerce.properties"})
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#Import({
SpringSecurityConfig.class})
public class AppConfig {
#Bean
public AuthenticatedWebApplication webApp() {
return new WicketApplication();
}
}
custom class from AbstractSecurityWebApplicationInitializer like:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(SpringSecurityConfig.class);
}
}
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>rcommerce</display-name>
<!-- WICKET FILTER-->
<filter>
<filter-name>wicket.rcommerce</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationFactoryClassName</param-name>
<param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
</init-param>
<init-param>
<param-name>applicationBean</param-name>
<param-value>webApp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.rcommerce</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- MDC FILTER -->
<filter>
<description>A servlet filter that inserts various values retrieved from the incoming http request into the MDC.</description>
<filter-name>MDCInsertingServletFilter</filter-name>
<filter-class>ch.qos.logback.classic.helpers.MDCInsertingServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MDCInsertingServletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>MoreMdcServletFilter</filter-name>
<filter-class>com.rudiwijaya.rcommerce.servlet.MoreMdcServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MoreMdcServletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- SPRING REST SERVLET-->
<servlet>
<servlet-name>spring-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<!-- <init-param> -->
<!-- use just the root WebApplicationContext -->
<!-- <param-name>contextConfigLocation</param-name> -->
<!-- <param-value>org.soluvas.sanad.app.ServletConfig</param-value> -->
<!-- <param-value></param-value> -->
<!-- </init-param> -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-web</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- SPRING REST FILTER-->
<filter>
<filter-name>httpPutFormFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpPutFormFilter</filter-name>
<servlet-name>spring-web</servlet-name>
</filter-mapping>
<!-- The SpringWebApplicationFactory will need access to a Spring Application
context, configured like this... -->
<!-- SPRING CONFIG -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.rudiwijaya.rcommerce.AppConfig</param-value>
</context-param>
<!-- LISTENERS -->
<listener>
<listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- ERROR PAGE HANDLING -->
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<!-- TIMEOUT -->
<session-config>
<session-timeout>120</session-timeout>
</session-config>
</web-app>
when I call session.signIn, got error like:
Root cause:
java.lang.NullPointerException
at com.rudiwijaya.rcommerce.WicketSession.authenticate(WicketSession.java:60)
at org.apache.wicket.authroles.authentication.AuthenticatedWebSession.signIn(AuthenticatedWebSession.java:66)
at com.rudiwijaya.rcommerce.pages.LoginButton.doAuthenticate(LoginButton.java:132)
at com.rudiwijaya.rcommerce.pages.LoginButton.onSubmit(LoginButton.java:165)
at org.apache.wicket.ajax.markup.html.form.AjaxButton$1.onSubmit(AjaxButton.java:113)
at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior$AjaxFormSubmitter.onSubmit(AjaxFormSubmitBehavior.java:215)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1307)
at org.apache.wicket.markup.html.form.Form.process(Form.java:976)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:797)
at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:171)
at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:155)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:601)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:258)
at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:241)
at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.invokeListener(ListenerInterfaceRequestHandler.java:248)
at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.respond(ListenerInterfaceRequestHandler.java:234)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:895)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
The error (it is httpSession is null) in line:
httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
What should I do, please?
Do you have more than one web container nodes ? With session replication ?
As a general rule you should never keep a hard reference to the Http Session. Especially in Wicket applications! Because if WicketSession is serialized and then deserialized this member field will be null!
Better lookup the HttpSession whenever you need it, i.e. extract((HttpServletRequest) request.getContainerRequest()).getSession(); in a method and call it when you need the session in the methods' bodies.

How to handle Navigation in Managed Bean?

I have a JSF 2.1 with Primefaces mobile project which should run on desktop and mobile platforms. I wrote a renderkit handler which provides required renderkit based on the device the web app is running on. I'm having tough time in redirecting a desktop page to a mobile page.
URL used to access : http://localhost:8080
My Application structure is :
root
- WebContent
--desktop
---login.xhtml
--mobile
---login.xhtml
--WEB-INF
---web.xml
---faces-config.xml
--META-INF
faces-config.xml
<application>
<view-handler>com.renderkit.CustomViewHandler</view-handler>
</application>
<navigation-rule>
<display-name>Desktop-Login</display-name>
<from-view-id>/desktop/login.xhtml</from-view-id>
<navigation-case>
<from-outcome>MOBILE</from-outcome>
<to-view-id>/mobile/login.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>AnalyzerUI</display-name>
<welcome-file-list>
<welcome-file>/desktop/login.xhtml</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>*.jsf</url-pattern>
<url-pattern>*.faces</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
</web-app>
User class, a Session scoped Managed Bean class for login.xhtml
#ManagedBean
#SessionScoped
public class User implements Serializable
{
private String name;
private String password;
#PostConstruct
public void myPostConstruct()
{
String renderKitId = FacesContext.getCurrentInstance().getViewRoot().getRenderKitId();
System.out.println(" renderKitId >>> " + renderKitId);
if (renderKitId.equalsIgnoreCase("PRIMEFACES_MOBILE"))
{
try
{
FacesContext.getCurrentInstance().getApplication(). getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null , "MOBILE");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
//getters and setters
}
CustomViewHandler
public class CustomViewHandler extends ViewHandlerWrapper
{
private ViewHandler wrapped;
public CustomViewHandler(ViewHandler wrapped)
{
this.wrapped = wrapped;
}
#Override
public ViewHandler getWrapped()
{
return this.wrapped;
}
#Override
public String calculateRenderKitId(FacesContext context)
{
HttpServletRequest req = (HttpServletRequest) context.getExternalContext().getRequest();
String userAgent = req.getHeader("user-agent");
String accept = req.getHeader("Accept");
System.out.println("userAgent ::: "+ userAgent+ " accept :: "+accept);
if (userAgent != null && accept != null) {
UAgentInfo agent = new UAgentInfo(userAgent, accept);
if (agent.isMobileDevice()) {
return "PRIMEFACES_MOBILE";
}
}
return this.wrapped.calculateRenderKitId(context);
}
}

Integrating Spring Security with Vaadin 7

I am new to vaadin 7. I am finding some problem with Spring Security Vaadin Integration. I am using JSP Login form to Login into my application. I am not able to log into my application, and I am unable to find the problem.
web.xml
<display-name>Vaadin Web Application</display-name>
<context-param>
<description>Vaadin production mode</description>
<param-name>productionMode</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>com.vaadin.ui.application.spring.ApplicationContextListener</listener-class>
</listener>
<servlet>
<servlet-name>TestApp</servlet-name>
<servlet-class>com.vaadin.ui.application.spring.SpringApplicationServlet</servlet-class>
<init-param>
<param-name>closeIdleSessions</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<description>Vaadin UIProvider class name</description>
<param-name>UIProvider</param-name>
<param-value>com.vaadin.ui.application.spring.ApplicationUIProvider</param-value>
</init-param>
<init-param>
<description>Vaadin application bean to start</description>
<param-name>UIBean</param-name>
<param-value>TestApplication</param-value>
</init-param>
<init-param>
<param-name>widgetset</param-name>
<param-value>com.vaadin.ui.application.AppWidgetSet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/home/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/VAADIN/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/schema/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>loginform.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>100</session-timeout>
</session-config>
SpringApplicationServlet.java
#Component
public class SpringApplicationServlet extends VaadinServlet {
private WebApplicationContext applicationContext;
private Class<? extends UI> applicationClass;
private String applicationBean;
private LocaleResolver localeResolver;
#SuppressWarnings("unchecked")
#Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
applicationBean = servletConfig.getInitParameter("applicationBean");
if (applicationBean == null) {
throw new ServletException(
"ApplicationBean not specified in servlet parameters");
}
applicationContext = WebApplicationContextUtils
.getWebApplicationContext(servletConfig.getServletContext());
applicationClass = (Class<? extends UI>) applicationContext
.getType(applicationBean);
initLocaleResolver(applicationContext);
}
private void initLocaleResolver(ApplicationContext context) {
try {
this.localeResolver = (LocaleResolver) context.getBean(
DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME,
LocaleResolver.class);
} catch (NoSuchBeanDefinitionException ex) {
this.localeResolver = new SessionLocaleResolver();
}
}
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
final Locale locale = localeResolver.resolveLocale(request);
LocaleContextHolder.setLocale(locale);
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(
request);
RequestContextHolder.setRequestAttributes(requestAttributes);
try {
super.service(new HttpServletRequestWrapper(request) {
#Override
public Locale getLocale() {
return locale;
}
}, response);
} finally {
if (!locale.equals(LocaleContextHolder.getLocale())) {
localeResolver.setLocale(request, response,
LocaleContextHolder.getLocale());
}
LocaleContextHolder.resetLocaleContext();
RequestContextHolder.resetRequestAttributes();
}
}
protected UI getNewApplication(HttpServletRequest request)
throws ServletException {
return (UI) applicationContext.getBean(applicationBean);
}
protected Class<? extends UI> getApplicationClass()
throws ClassNotFoundException {
return applicationClass;
}
Please help me out with some sample code to get this working.
Regards
Abhilash
You didn't write what error you have.Anyway, I see one defect: servlet is register as: TestApp
but mapped as: Test

Spring Don't accept my second login after an logout

I started with Spring Security framework. I set the framework. it works fine but my problem is at the logout function ...
when I disconnect. and I come to connect one more time he pass me on page access denied. whenever I am forced to restart tomcat for that he accepts my connection
My second Probleme :I tried to test the thing that speaks of time out session I stayed more than 1 min and when I come back I'm still on the same page. I do not know how to activate this option I think I configured on my security.xml but it doesn't work
This is My Sprinconfiguration
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:sec="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<sec:http auto-config="true" use-expressions="true">
<sec:intercept-url pattern="/pagess/**" access="hasRole('ROLE_USER')"/>
<sec:form-login login-page="/login.jsf" authentication-failure-url="/loginFailed.jsf" default-target-url="/pagess/Menu.jsf"/>
<sec:logout logout-success-url="/login.jsf" delete-cookies="JSESSIONID" invalidate-session="true"/>
<sec:session-management invalid-session-url="/login.jsf">
<sec:concurrency-control max-sessions="1"
error-if-maximum-exceeded="true" />
</sec:session-management>
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:jdbc-user-service data-source-ref="DataSource"/>
</sec:authentication-provider>
</sec:authentication-manager>
</beans:beans>
and this is my bean Loginbean
#ManagedBean(name="loginBean")
#SessionScoped
public class LoginBean {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String doLogin() throws ServletException, IOException {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
RequestDispatcher dispatcher = ((ServletRequest) context.getRequest())
.getRequestDispatcher("/j_spring_security_check?j_username=" + username
+ "&j_password=" + password);
dispatcher.forward((ServletRequest) context.getRequest(),
(ServletResponse) context.getResponse());
FacesContext.getCurrentInstance().responseComplete();
return null;
}
public String dologout() throws IOException {
FacesContext.getCurrentInstance().getExternalContext()
.invalidateSession();
this.username = "";
this.password = "";
ExternalContext context =FacesContext.getCurrentInstance().getExternalContext();
context.redirect(context.getRequestContextPath()
+ "/j_spring_security_logout");
FacesContext.getCurrentInstance().responseComplete();
return null;
}
}
this is WebXml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>PFE</display-name>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>trontastic</param-value>
</context-param>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<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>*.jsf</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/Test.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application.xml
/WEB-INF/spring_sec.xml
</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
</web-app>
I fixed My Problem ..there is one Listner misssing
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener

Spring security login/ logout issue

I have written custom UserDetailsService to validate user from database.First time it is working fine but when same user try to login after logout second time it is giving error.my application is based on
Spring 3.1 , Spring security with Pretty faces on tomcat 7
org.springframework.security.authentication.BadCredentialsException: Bad credentials
here is my configuration details web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5" metadata-complete="true">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/application-context.xml,
/WEB-INF/spring/application-context-security.xml
</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>redmond</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/application-context.xml,
/WEB-INF/spring/application-context-security.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/jcsb</url-pattern>
</servlet-mapping>
<!-- Pretty Face -->
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<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>*.jsf</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>org.springframework.security.access.AccessDeniedException</exception-type>
<location>/login.xhtml</location>
</error-page>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/index.html</location>
</error-page>
application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="com.swift.jcbs.web" />
<tx:annotation-driven />
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="view">
<bean class="com.suraj.jcbs.web.spring.ViewScope"/>
</entry>
</map>
</property>
</bean>
application-context-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:faces="http://www.springframework.org/schema/faces"
xmlns:int-security="http://www.springframework.org/schema/integration/security"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/integration/security http://www.springframework.org/schema/integration/security/spring-integration-security-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<sec:global-method-security
secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled">
</sec:global-method-security>
<!--
resource security
Note:
Access-denied-page is invoked when user is AUTHENTICATED but is not AUTHORIZED to access protected resources.
When user is NOT AUTHENTICATED, he is moved into form-login instead of access-denied-page.
-->
<sec:http access-denied-page="/access_denied.xhtml" use-expressions="true" auto-config="true" >
<sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:form-login login-page="/login.jsf"/>
<sec:intercept-url pattern="/secured/**" access="isAuthenticated()"/>
<sec:intercept-url pattern="/WEB-INF/faces/**" access="isAuthenticated()"/>
<sec:logout logout-url="/logout" logout-success-url="/secured/home" delete-cookies="JSESSIONID" />
<sec:session-management invalid-session-url="/secured/home">
<sec:concurrency-control error-if-maximum-exceeded="true" max-sessions="6"/>
</sec:session-management>
</sec:http>
<!--
manager responsible for loading user account with assigned roles
-->
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider
user-service-ref="userVerificationService"/>
</sec:authentication-manager>
#Service
public class UserVerificationService implements UserDetailsService {
private HashMap<String, org.springframework.security.core.userdetails.User> users = new HashMap<String, org.springframework.security.core.userdetails.User>();
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
org.springframework.security.core.userdetails.User user = users.get(username);
if (user == null) {
throw new UsernameNotFoundException("UserAccount for name \""
+ username + "\" not found.");
}
return user;
}
#PostConstruct
public void init() {
// sample roles
Collection<GrantedAuthority> adminAuthorities = new ArrayList<GrantedAuthority>();
adminAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
Collection<GrantedAuthority> userAuthorities = new ArrayList<GrantedAuthority>();
adminAuthorities.add(new SimpleGrantedAuthority("ROLE_REGISTERED"));
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
// sample users with roles set
users.put("admin", new org.springframework.security.core.userdetails.User("admin", "admin", enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, adminAuthorities));
users.put("user", new org.springframework.security.core.userdetails.User("user", "user", enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, userAuthorities));
}
#Service
public class AuthenticationServiceImpl implements AuthenticateService {
#Resource(name = "authenticationManager")
private AuthenticationManager authenticationManager;
public boolean login(String username, String password) {
try {
System.out.println("inside login");
System.out.println("AuthenticationServiceImpl user name " +username +" Pass = "+password);
Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
username, password));
SecurityContextHolder.getContext().setAuthentication(authenticate);
HttpUtils.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
return true;
} catch (AuthenticationException e) {
e.printStackTrace();
}
return false;
}
Here is my loginBean
public String process() {
System.out.println("user name " + username + " Pass = " + password);
if (authenticateService.login(username, password)) {
return "pretty:home";
} else {
FacesUtils.addErrorMessage("Invalid UserName or Password");
return null;
}
}
From Spring 3.1 onwards, the User Credentials are being erased which usually causes some problems. I worked around this problem by turning off the said feature.
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="eraseCredentialsAfterAuthentication" value="false"/>
</bean>
If you are using namespaces, you may use
<authentication-manager erase-credentials="false">

Resources