Spring MVC 3 I18N/MessageSource not working - java

I am trying to configure internazionalization in Spring MVC (using changing of locales via links), however, it doesn't seem to be working at all: default locale is always ru for some reason, though default is set to en, they are not changing using links, spring messages are displayed empty regardless of the chosen locale (messages_de, messages_en and messages_ru.properties DO exist at classpath (src/main/resources)). They contain e.g.
label.test=Russian
and i refer to them as
<spring:message code="label.test" />
in my JSPs. They are not being displayed like that.
I take it as even messageSource is not found, even though there are no errors or warnings. I'd really appreciate any help as I'm trying to figure it out for really long time. Apparently, I've missed some details, but I definitely can't catch the problem. Here are my configuration files (or most relevant parts).
root-context.xml
<context:component-scan base-package="... .dao" />
<context:component-scan base-package="... .service" />
<import resource="data.xml" />
<import resource="security.xml" />
mvc-dispatcher-servlet.xml
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="sitelocale" />
</bean>
</mvc:interceptors>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
data.xml
<!-- Transaction Manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<!-- //////////////////////////////////////////////////////////////////////////
" -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.databaseurl}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- ////////////////////////////////////////////////////////////////////////// -->
<!-- Hibernate SessionFactory configuration -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.tsystems.javaschool.kts.domain" />
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
</props>
</property>
</bean>
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC -->
<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/appServlet/mvc-dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<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>

You don't need to prefix the basename value with "classpath:", try to change it as follows:
<property name="basename" value="messages" />

Adding the following should allow you to change the lang with a URL parameter named "lang" (i.e. lang=en). This will allow you to override browser default settings and explicitly declare the language in use.
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
Also, ensure in the deployed webapp that the message files are located under WEB-INF/classes/ if you are going to use classpath:messages as a basename.

Also check if you add this at the top
<%# page contentType="text/html;charset=UTF-8" %>

Related

Spring database configuration issue

I am new to Spring-MVC, i am trying to create a Spring-MVC project that uses annotation in controller and also creates databases.
The application works fine, when i write all the xml code in spring-dispatcher-servlet.xml file, but when i separate spring database connection xml and spring servlet xml file, it stops working.
The following code successfully creates tables in database, but it fails to load controllers, it gives me 404 not found page when i try to hit any controller.
If i comment <listner> code in my web.xml file it successfully loads all the controllers, but no database operations performed.
Kindly guide me what i am doing wrong here.
web.xml
<!-- JPA -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring.xml</param-value>
</context-param>
<!-- Servlet Dispatcher -->
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
Spring.xml
<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.evantage.models" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/springDB" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<!-- This produces a container-managed EntityManagerFactory; rather than
application-managed EntityManagerFactory as in case of LocalEntityManagerFactoryBean -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="persistenceXmlLocation" value="/WEB-INF/persistence.xml" />
</bean>
<jpa:repositories base-package="com.evantagesoft.springmvctiles.repository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager"/>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Spring-dispatcher-servlet.xml
<context:component-scan base-package="com.evantage.controllers" />
<mvc:annotation-driven />
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
<property name="preparerFactoryClass"
value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory" />
</bean>
<!-- View Handler -->
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="favorPathExtension" value="true" />
<property name="mediaTypes">
<map>
<entry key="xml" value="text/xml" />
<entry key="json" value="application/json" />
<entry key="html" value="text/html" />
<entry key="less" value="text/html" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.tiles2.TilesView" />
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- <property name="prefix" value="/"/> -->
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</list>
</property>
</bean>
You need to add context:component-scan base-package="controller package" in dispatcher servlet xml to make it work.
Component scan is required to scan the package and register your controller classes

Error showing "Description: The requested resource is not available."

I am deploying my Spring-Hibernate web application on "https://app.j.layershift.co.uk/" server. But it is showing error "The requested resource is not available".
This is very small web application on Spring-Hibernate. I made a zip file and upload it on server but server gives error at time of deployment.
Dispatcher Servlet:
<bean id="cradentials" class="com.webscreen.bean.Cradentials" />
<bean id="cradentialsService" class="com.webscreen.service.CradentialsService"/>
<bean id="cradentialsDao" class="com.webscreen.dao.CradentialsDao"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<context:component-scan base-package="com.webscreen.controller"></context:component-scan>
<!-- we will manage transactions with annotations -->
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- we can use annotations -->
<context:annotation-config />
<mvc:annotation-driven />
<!-- data source for our database -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/screenshots" />
<property name="user" value="root" />
<property name="password" value="root" />
<property name="maxPoolSize" value="10" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<!-- configure hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.webscreen.bean.Cradentials</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
</beans>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

Spring MVC Url-Pattern DispatchServlet

I think I crashed my setup because my mapping isn't working any more and I don't know why. Here are my web.xml, applicationContext.xml payment-servlet.xml and payment.beans.xml.
**web.xml**
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- Add Support for Spring -->
<!-- Default applicationContext location: /WEB-INF/applicationContext.xml -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- exposes the request to the current thread -->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- springapp payment servlet -->
<servlet>
<servlet-name>payment</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- <param-value>classpath:/spring/servlet/payment-servlet.xml</param-value> -->
<param-value>file:**/webapp/META-INF/spring/servlet/payment-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>payment</servlet-name>
<url-pattern>/payment/*</url-pattern>
<url-pattern>/paymentExternalData</url-pattern>
<url-pattern>/paymentInternalData</url-pattern>
</servlet-mapping>
<!-- Welcome files -->
<welcome-file-list>
<welcome-file>payment.jsp</welcome-file>
<welcome-file>payment.html</welcome-file>
</welcome-file-list>
</web-app>
**applicationContext.xml**
<context:annotation-config />
<!-- payment servlet
<import resource="classpath:/spring/payment.beans.xml"/> -->
<import resource="file:**/webapp/META-INF/spring/payment.beans.xml"/>
<!-- Auto scan the components -->
<context:component-scan
base-package="com.app.payment.model.PaymentUser" />
**payment-servlet**
<!-- Auto scan the components -->
<context:component-scan base-package="at.dt_i.primesign.payment" />
<!-- Payment controller -->
<bean class="at.dt_i.primesign.payment.controller.PaymentController">
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- PropertyPlaceholderConfigurer
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="configuration">
<property name="properties" ref="configuration" />
</bean> -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/configuration.properties</value>
</property>
</bean>
**payment.beans.xml**
<context:annotation-config />
<tx:annotation-driven />
<bean id="paymentDao" class="com.app.payment.model.PaymentDAOImpl" />
<bean id="paymentService" class="com.app.payment.PaymentServiceImpl" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="paymentTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="paymentEntityManagerFactory" />
</bean>
<!-- -->
<bean id="paymentJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="${paymentJpaVendorAdapter.generateDdl}" />
<property name="databasePlatform" value="${paymentJpaVendorAdapter.databasePlatform}" />
</bean>
<bean id="paymentEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="profileDataSource" />
<property name="jpaVendorAdapter" ref="paymentJpaVendorAdapter" />
<property name="persistenceUnitName" value="payment" />
</bean>
My first question: Is my structure right or is there a better solution.
the main goal is to operate with to controller methods /paymentInternalData and /paymentExternalData. But I think the dispatchServlet loads something different because the mapping is not working it only shows the welcome page. but not the 2 sub pages.
I know this is mainly code but I'm not sure what to post, so I posted everything. hopefully anybody can help.
I think your Url-pattern for servlet is correct :
<servlet-mapping>
<servlet-name>payment</servlet-name>
<url-pattern>/payment/*</url-pattern>
<url-pattern>/paymentExternalData</url-pattern>
<url-pattern>/paymentInternalData</url-pattern>
</servlet-mapping>
But the
file:**/webapp/META-INF/spring/servlet/payment-servlet.xml
is not able to load the payment-servlet.xml file.
If your META-INF is under webapp directory then you can do this :
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- <param-value>classpath:/spring/servlet/payment-servlet.xml</param-value> -->
<param-value>/META-INF/spring/servlet/payment-servlet.xml</param-value>
</init-param>
or
Remove the init-param block and move payment-servlet.xml under webapp/WEB-INF/ directory where web.xml present.

Spring Security - how I can enable Method Security annotations?

There is lot of similar questions at StackOverflow, but I can't find any answered :(
I have web.xml like:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-web.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>
and trying to configure method security with annotations. As I see it must be done by <sec:global-method-security pre-post-annotations="enabled"/>, placed at same context as other components, spring-web.xml at my case. So I have following spring-web.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.cleanplates.apiserv"/>
<sec:global-method-security pre-post-annotations="enabled"/>
</beans>
and spring-security.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/**"
filters="
usernamePasswordProcessingFilter,
rememberMeFilter,
anonymousProcessingFilter,
exceptionTranslationFilter,
filterInvocationInterceptor"/>
</sec:filter-chain-map>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter"/>
</list>
</property>
</bean>
<bean id="anonymousProcessingFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="********"/>
<property name="userAttribute">
<bean class="org.springframework.security.core.userdetails.memory.UserAttribute">
<property name="authoritiesAsString">
<list>
<value>ROLE_ANONYMOUS</value>
</list>
</property>
<property name="password" value="none"/>
</bean>
</property>
</bean>
<bean id="usernamePasswordProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="filterProcessesUrl" value="/auth/password"/>
<property name="usernameParameter" value="username"/>
<property name="passwordParameter" value="password"/>
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="*******"/>
<property name="alwaysRemember" value="true"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="******"/>
</bean>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
</property>
</bean>
<bean id="filterInvocationInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="securityMetadataSource">
<sec:filter-security-metadata-source>
<sec:intercept-url pattern="/**" access="ROLE_ANONYMOUS,ROLE_USER" method="GET"/>
<sec:intercept-url pattern="/**" access="ROLE_ADMIN" method="POST"/>
<sec:intercept-url pattern="/**" access="ROLE_ADMIN" method="PUT"/>
<sec:intercept-url pattern="/**" access="ROLE_ADMIN" method="DELETE"/>
</sec:filter-security-metadata-source>
</property>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
</bean>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<bean class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="***"/>
</bean>
<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="saltSource">
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="salt"/>
</bean>
</property>
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>
</list>
</property>
</bean>
<bean id="myUserDetailsService" class=".UserDetailsServiceImpl">
</bean>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
</bean>
</beans>
The problem that after adding <sec:global-method-security all controllers stop working. And I have following in logs:
PageNotFound:noHandlerFound:947 - No mapping found for HTTP request with URI [/some/page] in DispatcherServlet with name 'spring'
Everything is working when i remove this global-security element. If i'm adding it into spring-security.xml - nothing changes. Seems that it's not used, because methods annotated with #PreAuthorize("hasRole('ROLE_ADMIN')") (or any other role) are accessible by anyone.
PS I'm using Spring 3.0.5.RELEASE and Spring Security 3.0.5.RELEASE
After you enable <sec:global-method-security> spring security creates proxies for your controllers. spring-mvc can't find annotations like #RequestMapping on bean in this case. If you want to use security annotations on your controllers you should extract interface of controller and put mvc annotations on it.
Spring documentation contains following note about this:
NOTE: When using controller interfaces (e.g. for AOP proxying), make sure to consistently put all your mapping annotations - such as #RequestMapping and #SessionAttributes - on the controller interface rather than on the implementation class.

Can't get spring-security.xml right

I have my spring security set up to do basic authentication to a database with no issues, however I would like to add custom login/logout and admin pages as well as md5 encryption on passwords w/ salt.
I keep hitting walls trying to get either of these features to work, and all the examples online seem to be using and declaring like that instead of using bean declarations like I am. This makes it more difficult because options in examples don't seem to directly translate into bean properties.
Here is my web.xml - I am using Spring Security 3.0:
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/builder-servlet.xml
/WEB-INF/builder-service.xml
/WEB-INF/builder-data.xml
/WEB-INF/builder-security.xml
</param-value>
</context-param>
<servlet>
<servlet-name>builder</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>builder</servlet-name>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.docx</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.springframework.security.web.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
And here is my builder-security (mind the disorganization):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<!--<s:authentication-manager>
<s:authentication-provider ref="authenticationProvider"/>
</s:authentication-manager>-->
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<s:filter-chain-map path-type="ant">
<s:filter-chain pattern="/**"
filters="securityContextPersistenceFilter,
exceptionTranslationFilter,
authenticationProcessingFilter,
filterSecurityInterceptor,
anonymousAuthenticationFilter"/>
</s:filter-chain-map>
</bean>
<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>
<bean id="authenticationProcessingFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
<ref bean="anonymousAuthenticationProvider"/>
</list>
</property>
</bean>
<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<!--<property name="passwordEncoder" ref="md5PasswordEncoder"/>-->
<!--<property name="saltSource" ref="systemWideSaltSource"/>-->
<property name="userDetailsService" ref="authenticationDao"/>
<property name="userCache" ref="userCache"/>
</bean>
<bean id="md5PasswordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
</bean>
<bean id="systemWideSaltSource" class="org.springframework.security.authentication.dao.SystemWideSaltSource">
<property name="systemWideSalt" value="XXXX"/>
</bean>
<bean id="userCache" class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
<property name="cache" ref="ehcache"/>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"/>
<property name="cacheName" value="userCache"/>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="ehcache.xml"/>
</bean>
<bean id="authenticationDao" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="SpecBuilder"/>
</bean>-->
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.html"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<property name="decisionVoters">
<list>
<ref bean="voter"/>
</list>
</property>
</bean>
<bean id="voter" class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value="ROLE_"/>
</bean>
<bean id="anonymousAuthenticationFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="foobar"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider" class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="foobar"/>
</bean>
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="objectDefinitionSource">
<s:filter-invocation-definition-source>
<s:intercept-url pattern="/login*" access="ROLE_ANONYMOUS"/>
<s:intercept-url pattern="/**" access="ROLE_USER"/> <!-- isAuthenticated() probably better -->
</s:filter-invocation-definition-source>
</property>
</bean>
</beans>
Right now I am trying to get login.html to all anonymous access, yet all I get is an infinite security loop.
Is there a reason I shouldn't be using bean declarations for this? Because not very many people seem to be doing so. I'd rather not change the whole thing if there is no advantage to doing it. There has to be something wrong with it or a better place to go to get bean declaration references and examples, because most all searches turn up the other style of implementing spring security.
Step-by-step spring security explained:
http://blog.solidcraft.eu/2011/03/spring-security-by-example-set-up-and.html
Good luck!
After a fair bit of research and testing, I've solved it.
The built in security namespace does a good chunk of the work for you. Creating each filter and manager bean by bean is a good way to customize things, but it makes it quite bit more difficult and it's not really necessary.
My final code involves a custom user class that includes a salt value and a custom dao class to enforce the use of the salt. Everything else is done through use of the security namespace.
builder-security.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<s:http auto-config="true" use-expressions="true">
<s:intercept-url pattern="/login*" access="permitAll"/>
<s:intercept-url pattern="/*" access="hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')"/>
<s:form-login login-page="/login.html"/>
<s:logout logout-url="/logout"/>
</s:http>
<s:authentication-manager alias="authenticationManager">
<s:authentication-provider user-service-ref="userDetailsService">
<s:password-encoder ref="passwordEncoder">
<s:salt-source ref="saltSource"/>
</s:password-encoder>
</s:authentication-provider>
</s:authentication-manager>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
<property name="userPropertyToUse" value="salt"/>
</bean>
<bean id="userDetailsService" class="builder.webapp.security.CustomJdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="enableAuthorities" value="true"/>
<property name="enableGroups" value="false"/>
<property name="usersByUsernameQuery"
value="select username,password,enabled,salt from users where username = ?"/>
</bean>
</beans>

Categories

Resources