具有Spring Security的AngularJS Web应用程序


问题内容

我正在致力于在AngularJS应用程序中实现Spring
Security。我对这两种技术都比较陌生,并且发现了一些非常有用的站点,其中包含有关如何实现AngularJS和Spring
Security的教程和示例。

我目前的问题在于将URL路径限制为某些用户。IT听起来像是一个简单的问题,但是我沉迷于文档中,试图找出以前必须解决的问题。

在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>

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>

部署应用程序后,我可以访问URL(localhost:8080 / app),并且按预期进入登录页面。通过身份验证后,我也会按预期进入启动屏幕(/#/
splash)。但是,如果我使用“用户”凭据登录,则应该从/
inventory路径进行限制。无论我尝试什么(/#/库存,/库存,#/库存等),我都无法限制资源。我已经在直接从应用程序目录访问HTML页面的应用程序上测试了此配置,并且看起来运行良好,因此,我相信它与AngularJS控制器路由请求并使用该哈希标记有关。

我在研究此问题时发现的另一个兴趣点是,因为我们使用来自多个来源的模板来编译每个页面,所以在不破坏应用程序的情况下,不能使用$
locationProvider设置HTML5模式。

如果有人对这个问题有任何见识,将不胜感激。我敢肯定这是某个地方,但是对于我一生来说,我什么也找不到。谢谢!


问题答案:

您似乎将Angular的客户端URL处理(基于哈希,例如’/#/ splash)与Spring MVC(以及Spring
Security的)服务器端URL处理混淆了。

请记住,Spring Security可确保对服务器端URL的访问安全,并且Angular是单页客户端库。

首次访问Angular页面时,是从服务器获取的,Spring Security可以根据登录限制访问。

如果您仍处于客户端的单页Angular环境中,并通过Angular导航到URL中带有哈希值的“页面”(请参阅AngularJS $
location指南中有关hashbang
URL的信息
),则您未在发出服务器请求。您正在请求Angular渲染不同的模板或状态。这是客户端行为,因此不涉及Spring
Security。当您访问模板HTML文件(Spring可能会在不进行身份验证的情况下静态返回该HTML文件)或设置了REST
api从服务器获取数据(通常返回JSON格式的数据供您的应用程序使用)时,您会发出服务器请求。

我相信,要使此工作有效,受保护资源(“
/清单”)的数据将不必包含在主应用程序中,而需要单独的服务器端资源。这可以包括页面的HTML模板和/或数据。您的AngularJS应用程序应该能够识别该资源不可用,并向用户显示一些内容以传达缺少授权的情况。