spring mvc prefix text to all urls - spring-mvc

I want to add the following prefix to all my urls
/login should now be /springmvc/login
What are the changes that needs to be made. I add the following but no use. I also tried a updating all of the following no luck, sometime the login page works but the result page which is mostly return "login" does not work
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="pathPrefix" value="springmvc" />
<property name="caseSensitive" value="false" />
</bean>
I have updated my controller as follows
#RequestMapping("/springmvc")
public class LoginController {
my web.xml is as follows, I havn't updated those
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
my spring security related code is as follows
<http access-decision-manager-ref="accessDecisionManager" auto-config="true">
<intercept-url pattern="/welcome*" access="ADMIN" />
<form-login login-page="/login" default-target-url="/welcome"
authentication-failure-url="/loginfailed" />
<logout logout-success-url="/logout" />
</http>

I would start by adding '/springmvc' to the mapping for your dispatcher servlet.
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/springmvc/*</url-pattern>
</servlet-mapping>
That should give you a common prefix for your controllers. You may have to tweak spring security separately to get the login/logout links working. E.G.
<http access-decision-manager-ref="accessDecisionManager" auto-config="true">
<intercept-url pattern="/springmvc//welcome*" access="ADMIN" />
<form-login login-page="/springmvc/login" default-target-url="/springmvc/welcome"
authentication-failure-url="/springmvc/loginfailed" />
<logout logout-success-url="/springmvc/logout" />
</http>
The ControllerClassNameHandlerMapping class is for setting up "convention over configuration" mappings. In other words the path is derived from the class/package name which means you don't need the #RequestMapping annotation at all.

Related

Spring Security 404 error

I want to use spring security for authentification but when I try to access the site, I get the 404 error on all requests. I'm trying to debug this for few days, but nothing work for me.
Here is my web.xml :
<!-- Spring MVC -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-database.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- 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>
spring-security.xml:
<context:component-scan base-package="com.example.users.service"/>
<http auto-config="true" use-expressions="true" authentication-manager-ref="authManager">
<intercept-url pattern="/j_spring_security_check" access="permitAll"/>
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />
<access-denied-handler error-page="/403" />
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" />
<csrf />
</http>
<authentication-manager id="authManager">
<authentication-provider user-service-ref="myUserDetailsService" />
</authentication-manager>
spring-database.xml:
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="12345678" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.example.users.model"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
and mvc-dispatcher-servlet.xml:
<context:component-scan base-package="com.example.*" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Any help would be greatly appreciated.
Thanks.
We don't know what version of Spring Security you are using, but if you have 4.X.X then this url won't work: /j_spring_security_check. They have changed it to /login.
Here is the docs.
I think this config should do the trick:
<http auto-config="true" use-expressions="true" authentication-manager-ref="authManager">
<form-login
login-page="/login"
default-target-url="/welcome"
always-use-default-target="true"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password"/>
<access-denied-handler error-page="/403" />
<intercept-url pattern="/**" access="isAuthenticated()"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/login" access="permitAll"/>
<logout logout-success-url="/login?logout" />
<csrf />
</http>
Assuming Dmitriy might have solved this by now, I am answering on the hopes that it may be useful for others who stumble upon on this issue.
I cannot find the spring mvc dispatcher servlet config xml.
We dont need to add component scan specially in the spring security xml configuration if its already taken care in the spring configuration.
The intercept-url pattern="/j_spring_security_check" access="permitAll" may not be required. Spring security is intelligent, it will only apply security for the url pattern mentioned. All other urls are free to access.
Depending on Spring security version, /j_spring_security_check or /login url should be used in the form action. Former is used in Spring 3.x and latter is used in Spring 4.x
login-page attribute in form-login must match a url in the spring mvc application through controller mapping or xml mapping.
Finally, important thing is, if you mess up a single config in spring security xml, spring will let you run the app but it will always result in 404. So make sure you have all urls mapped to controller mapping, all pages are resolvable in the spring mvc application.
For example, if the access-denied-handler error-page="/403" element cannot find /403 mapping then it will result in 404 error though the user is authenticated and authorized successfully.
if you debug the spring security framework how all the filters are working, you can see how your application is behaving.
<i><debug/></i> element in spring security can help.
Please let me know if this helps.

No mapping found for HTTP request with URI [/favicon.ico]

I can't recall what I have changed on my code but whenever I click on any links on my web it gives me this :
WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/favicon.ico] in DispatcherServlet with name 'mvc-dispatcher'
A portion of my web.xml
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
some configuration of my mvc-dispatcher-servlet.xml
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
<beans:property name="order" value="1" />
</beans:bean>
<!-- testing for pdf export -->
<beans:bean class="org.springframework.web.servlet.view.XmlViewResolver">
<beans:property name="location" value="/WEB-INF/spring-pdf-views.xml" />
<beans:property name="order" value="0" />
</beans:bean>
Other than that everything works fine, means any page is loaded correctly without any error. May I know what might cause this ? And who is using that .ico image ?
Most web browsers attempt to fetch a site's favicon at the root of the context with a request for the /favicon.ico resource automatically. In your case is not handled by any configured Spring mapping.
If you have a favicon at /favicon.ico or in another location you could configure a mapping in Spring to resolve the request to a valid resource:
<mvc:resources mapping="/favicon.ico" location="/favicon.ico" />
The favicon.ico : icon in the browser tab
Since Spring Security are using
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Did you exclude the favicon.ico from filtering by Spring Security?
<http pattern="/favicon.ico" security="none" />
Try to locate favicon.ico in your html page as below:
<html>
<head>
<link href="[YOUR_FAVICON_PATH]/favicon.ico" rel="icon" type="image/x-icon" />
</head>
</html>

Two DispatcherServlets and DelegatingFilterProxy do not work together

There ara two DispatcherServlets in my app. One is for jsp service and dispatches admin's addresses.
<servlet>
<servlet-name>adminServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/adminServlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>adminServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Second DispatcherServlet dispatches addresses where xml or json are sending.
<servlet>
<servlet-name>userServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/userServlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>userServlet</servlet-name>
<url-pattern>/user/*</url-pattern>
</servlet-mapping>
There is also DelegatingFilterProxy to ensure 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>
Security context configuration file:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login.do"
access="permitAll" requires-channel="http" />
<intercept-url pattern="/*"
access="hasRole('ROLE_USER')" requires-channel="http" />
<intercept-url pattern="/admin/*"
access="hasRole('ROLE_ADMIN')" requires-channel="http" />
<form-login login-page="/login.do"
login-processing-url="/loginProcess" username-parameter="user"
password-parameter="password" default-target-url="/admin" />
<logout logout-url="/logout.do"
invalidate-session="true" />
<remember-me key="secCh4"
token-validity-seconds="3600" data-source-ref="dataSource" />
<session-management
session-fixation-protection="newSession">
</session-management>
<intercept-url pattern="/user/*" access="hasRole('ROLE_USER')" />
</http>
The part of service which is dispatched by adminServlet need authentication and is secured, but the part which is dipatched by userServlet is completely unsecured and any authentication is not necessary. I don't know why, I set url-pattern in DelegatingFilterProxy to /* and i also set
<intercept-url pattern="/user/*" access="hasRole('ROLE_USER')" />
Any ideas?
DelegatingFilterProxy has nothing to do with DispatcherServlet. In fact, Spring MVC is not needed and you can use any other frame, like Struts.
With your rule <intercept-url pattern="/user/*" access="hasRole('ROLE_USER')" /> you are specifying to intercept urls like /user/list/ or /user/4, but not /user/4/save. If you want to intercept all urls starting with /user/ try with <intercept-url pattern="/user/**" access="hasRole('ROLE_USER')" />. You can read a little more here.
Anyway, remember that intercept-url order is important, too.

Spring OAuth2 - ensure call to OAuth2ProtectedResourceFilter

How do I ensure that a call is being made to the OAuth2ProtectedResourceFilter when a request is sent with the oauth_token in the Authorization header?
It always passes through a filter if it is mapped properly
As mentioned, everything that you want to be secured, needs to go through a spring security filter:
Here a sample how a filter is mapped in front of the servlet (the spring MVC DispatcherServlet used for the authorization endpoints)
You could additionally map the same filter to any other servlet, for example to a jersey servlet you have configured.
In /WEB-INF/web.xml you need a filter-mapping like:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<servlet-name>spring-dispatcher</servlet-name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
To ensure every call to '/*', or whatever pattern, is filtered you use http from the spring security namespace and a filter called OAuth2AuthenticationProcessingFilter, that will watch out for the Bearer Authorization header, you will need something like this in your /WEB-INF/spring-mvc-dispatcher-servlet.xml or where ever your spring security is configured:
<http pattern="/**"
create-session="never"
authentication-manager-ref="userAuthenticationManager"
access-decision-manager-ref="accessDecisionManager"
use-expressions="true">
<anonymous enabled="false" />
<custom-filter ref="oAuth2AuthenticationFilter" position="PRE_AUTH_FILTER" />
<access-denied-handler ref="oAuthAccessDeniedHandler" />
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
<beans:bean id="oAuth2AuthenticationFilter" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
<beans:property name="authenticationManager" ref="userAuthenticationManager"/>
<beans:property name="authenticationEntryPoint" ref="oAuthAuthenticationEntryPoint"/>
</beans:bean>

spring webmvc mapping the jsp (without controllers)

I am trying to get my hands on Spring 3 web-mvc. I have a simple page link (you know.. <a href="xyz"> thing.
Somehow spring mvc doesn't like that.. eer.. well, my spring config is not working how i would like it to be.
I tried with DefaultRequestToViewNameTranslator but that didn't help. I think its something to do with what "Handler" spring dispatcher servlet chooses.. but I am not able to grasp those things yet. Log output did not help much either.
Can someone help?
Here is web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Reads request input using UTF-8 encoding -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Handles all requests into the application -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/appServlet/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
And spring config:
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.mycompany.mvc" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<!-- Forwards requests to the "/" resource to the "welcome" view -->
<mvc:view-controller path="/" view-name="index"/>
<!-- Configures Handler Interceptors -->
<mvc:interceptors>
<!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/images/**" location="/images/" />
<!-- Saves a locale change using a cookie -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
<!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages" />
<property name="cacheSeconds" value="0" />
</bean>
<!-- Automatic resolution of the view names.. Convention over configuration -->
<bean id="viewNameTranslator" class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/content/"/>
<property name="suffix" value=".jsp"/>
</bean>
And jsp where link is defined:
<li>flot integration</li>
And the log file output:
DEBUG o.s.web.servlet.DispatcherServlet:693 - DispatcherServlet with name 'Spring MVC Dispatcher Servlet' processing GET request for [/demo/flot]
WARN o.s.web.servlet.PageNotFound:947 - No mapping found for HTTP request with URI [/demo/flot] in DispatcherServlet with name 'Spring MVC Dispatcher Servlet'
DEBUG o.s.web.servlet.DispatcherServlet:674 - Successfully completed request
Controller should handle user's request and in your case no controller which mapped to this URL. When controller found, it performs some logic and returns view name which will be used to represent server's response. So, view name translator called only after controller and only for deduce full path to particular JSP file.
Try to add
<mvc:view-controller path="demo/flot" view-name="demo/flot"/>
(Also, you probably may try to omit view-name attribute, but I don't sure.)
Currently.. following worked..
Though the property /** might be an issue for me later when I add the controllers too.
But I can customize the .jsp file url
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/**">urlFilenameViewController</prop>
</props>
</property>
</bean>
<bean id="urlFilenameViewController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
Using spring-webmvc 3.0.6.RELEASE this worked for me:
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<view-controller path="secure/*" view-name="secure/index"/>
<view-controller path="secure/extreme/*" view-name="secure/extreme/index"/>
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
Beans annotated with #Controller and #RequestMapping are called on the appropriate url, any url like secure/* and secure/extreme/* is handled by WEB-INF/views/secure/index.jsp and WEB-INF/views/secure/extreme/index.jsp respectively
I am using spring web 3.2.1 and I have only internal resolver and annotations based config. The jsp files view are accessible by default without using controller i.e not coded in any controller at return value of the mapped controller method. I guess there is some implicit rule.
Putting
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages" />
<property name="cacheSeconds" value="0" />
</bean>
in application-context.xml resolved the issue for me. The view which does not have a controller(request mapping) will not load if we put these things in servlet.xml. I tried putting these things in application-context.xml and it worked for me. Thanks!!!
After version 3.1 there is WebMvcConfigurerAdapter, so you can put the mapping in configuration like this:
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("/index");
}
}

Resources