Веб-приложение AngularJS с защитой Spring

Я работаю над реализацией Spring безопасности в приложении AngularJS. Я относительно новичок в обеих технологиях, и я нашел несколько очень полезных сайтов с учебниками и примерами того, как реализовать AngularJS и Spring Безопасность.

В настоящее время моя проблема заключается в ограничении путей URL для определенных пользователей. Это звучит как простая проблема, но я утонул в документах, пытаясь выяснить проблему, которая должна была быть решена ранее.

В AngularJS в URL-адресе есть хеш-метка при навигации по различным URL-адресам, что, по-видимому, вызывает проблему с Spring. Ошибка не возникает, но ресурс не ограничен. Мой код ниже:

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>
</web-app>

приложение-servlet.xml

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:intercept-url></sec:intercept-url></sec:intercept-url></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></sec:user></sec:user-service>
 </sec:authentication-provider>
</sec:authentication-manager>
</context:property-placeholder></beans>

Когда приложение развернуто, я могу получить доступ к URL (localhost: 8080/app), и я приветствую страницу входа в систему, как и ожидалось. Как только я пройду проверку подлинности, я также занесен на экран заставки (/#/splash), как и ожидалось. Однако, если я вхожу в систему с использованием учетных данных "user", я должен быть ограничен из пути/инвентаря. Независимо от того, что я пытаюсь (/#/инвентарь, инвентарь, #/инвентарь и т.д.), Я не могу ограничить ресурс. Я тестировал эту конфигурацию на приложении, которое обращается к HTML-страницам непосредственно из каталога приложения, и, похоже, работает нормально, поэтому я убежден, что это имеет какое-то отношение к контроллеру AngularJS, маршрутизирующему запросы и использующему эту метку.

Еще одна интересная вещь, которую я обнаружил при исследовании этого, заключалась в том, что, поскольку мы используем шаблоны из нескольких источников для компиляции каждой страницы, мы не можем использовать $locationProvider для установки режима HTML5 без нарушения приложения.

Если у кого-то есть понимание этой проблемы, было бы весьма полезно. Я уверен, что это было где-то, но для моей жизни я ничего не мог найти. Спасибо!

1 ответ

Кажется, вы запутываете обработку URL-адресов на стороне клиента Angular (на основе хэшей, например "/#/splash" ) с помощью обработки URL-адресов Spring MVC (и, следовательно, Spring Security).

Помните, что Spring Безопасность обеспечивает доступ к URL-адресам на стороне сервера и что Angular является одностраничной клиентской библиотекой.

При первом доступе к вашей странице Angular вы получаете ее с сервера, а Spring Безопасность может ограничить доступ в зависимости от входа.

Если вы все еще находитесь в своей одностраничной среде Angular на клиенте и перемещаетесь через Angular на страницу с хешем в URL-адресе (см. AngularJS $location guide about hashbang URLs), вы не делаете запрос на сервер. Вы запрашиваете Angular для отображения другого шаблона или состояния. Это поведение на стороне клиента, поэтому Spring Безопасность не задействована. Вы делаете запрос сервера при доступе к HTML файлу шаблона (который Spring может вернуться статически без проверки подлинности), или если вы настроили REST api для получения данных с вашего сервера (как правило, возвращающие форматированные данные JSON для использования вашего приложения).

Я считаю, что для выполнения этой работы данные для вашего защищенного ресурса ( "/inventory" ) не должны включаться в основное приложение, требуя отдельный серверный ресурс. Это может включать либо шаблон HTML для страницы, и/или данные. Ваше приложение AngularJS должно уметь распознавать, что этот ресурс недоступен, и показывать пользователю что-либо, чтобы сообщить об отсутствии авторизации.

licensed under cc by-sa 3.0 with attribution.