I am working on implementing Spring Security in an AngularJS application. I am relatively new to both technologies, and I have found several very helpful sites with tutorials and examples of how to implement AngularJS and Spring Security.
My problem currently lies in restricting URL paths to certain users. IT sounds like a simple problem, but I have drowned myself with documentation trying to figure out a problem that must have been solved previously.
In AngularJS, there is a hash mark in the URL when navigating to different URLs and that seems to cause a problem with Spring. There is no error thrown, but the resource is not restricted. My code is below:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>
/WEB-INF/paperwebapp-servlet.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>webapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>*</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webapp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>
<!-- Apply Spring Security Filter to all Requests -->
<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>
app-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="file:${catalina_home}/conf/application.properties" />
<mvc:view-controller path="/" view-name="/resources/index.html"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<import resource="spring-security.xml" />
</beans>
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<context:property-placeholder location="file:${catalina_home}/conf/application.properties" />
<sec:http auto-config='true'>
<sec:intercept-url pattern="/access/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<sec:intercept-url pattern="/*" access="ROLE_USER" />
<sec:intercept-url pattern="/#/inventory" access="ROLE_ADMIN" />
<sec:form-login login-page="/access/login.jsp" default-target-url="/#/splash"
always-use-default-target="true" />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />
<sec:user name="user" password="user" authorities="ROLE_USER" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
When the application is deployed, I can access the URL (localhost:8080/app) and I am greeted with a login page as expected. Once I am authenticated, i am brought to the splash screen (/#/splash) also as expected. However, if I log in using the "user" credentials, I should be restricted from the /inventory path. No matter what I try (/#/inventory, /inventory, #/inventory, etc) I cannot get the resource to be restricted. I have tested this configuration out on an application that accesses HTML pages directly from the application directory and it seems to work fine, thus I am convinced that it has something to do with the AngularJS controller routing the requests and using that hash mark.
Another point of interest I discovered in researching this was that because we are using templates from multiple sources to compile each page we cannot use the $locationProvider to set HTML5 mode without breaking the application.
If anyone has any insight into this problem, it would be greatly appreciated. I am sure this has been somewhere, but for the life of me I could not find anything. Thank you!