无法在现有应用程序中集成 Spring Security

Posted

技术标签:

【中文标题】无法在现有应用程序中集成 Spring Security【英文标题】:unable to integrate spring security in existing application 【发布时间】:2013-04-23 01:45:40 【问题描述】:

我无法找出我在 Spring 安全集成中的问题。我已经花了2-3天了。所以,请帮助我。

下面是我的 web.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>cdl</display-name>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>startUpServlet</servlet-name>
        <servlet-class>com.qait.cdl.commons.startup.StartUpServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>startUpServlet</servlet-name>
        <url-pattern>/startUpServlet.htm</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>

    <context-param>
        <param-name>CDL_ENV</param-name>
        <param-value>staging</param-value>
    </context-param>

    <listener>
        <listener-class>com.qait.cdl.commons.startup.CdlContextListner</listener-class>
    </listener>

    <!-- Session timeout -->
    <session-config>
        <session-timeout>600</session-timeout>
    </session-config>

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

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>
     WEB-INF/applicationContext.xml
     WEB-INF/dispatcher-servlet.xml
     </param-value>
    </context-param>


</web-app>

下面是我的 applicationContext.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">

     <import resource="classapth*:spring/SpringSecurityConfig.xml" />
<!--      <bean name="springSecurityFilterChain" class="org.springframework.web.filter.OncePerRequestFilter"/> -->
</beans>     

下面是我的 SpringSecurityConfig.xml

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

 <security:http auto-config="true" use-expressions="true">
    <security:intercept-url pattern="/displayAdminPage.htm" access="hasRole('ROLE_ADMIN')" />

    <security:form-login  login-page="/login.htm" authentication-failure-url="/login.htm"/>
    <security:logout logout-url="/logout.htm" logout-success-url="/login.htm"/>
    <security:access-denied-handler error-page="/login.htm" />
</security:http>

<security:authentication-manager>
    <security:authentication-provider user-service-ref="userService" >
    </security:authentication-provider>
</security:authentication-manager>

下面是我的 dispatcher-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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- Message resource -->
    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>messages</value>
                <value>error</value>
            </list>
        </property>
    </bean>

    <!-- Imports all configuration files -->
    <import resource="classpath*:spring/*.xml" />
    <import resource="classpath*:spring/*/*.xml" />

    <!-- Interceptor mapping -->
    <bean id="handlerMapping"
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        <!-- <property name="interceptors" ref="cdlInterceptor" /> -->
        <property name="interceptors" ref="cdlSessionInterceptor"></property>
    </bean>

    <!-- Tiles view resolver and configuration -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
        <property name="order" value="1" />
    </bean>

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles-defs.xml</value>
            </list>
        </property>
    </bean>

    <!-- XmlView Resolver -->
    <bean class="org.springframework.web.servlet.view.XmlViewResolver">
        <property name="location" value="/WEB-INF/spring-Xmlviews.xml" />
        <property name="order" value="0" />
    </bean>

    <!-- MultipartResolver for file upload -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

    <bean id="rssViewer" class="com.qait.cdl.rssfeed.view.CustomRssViewer" />

    <!-- Default view resolver mapping <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
        <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property 
        name="suffix"> <value>.jsp</value> </property> <property name="order" value="1" 
        /> </bean> -->
</beans>

我有以下疑问。

    是否需要在 web.xml 中添加“过滤器”标签,如果是,那么为什么? 在我的应用程序中,我有两个应用程序上下文(一个用于 spring security,另一个用于 dispatcher-servlet),springSecurityConfig.xml 是否可以访问 dispatcher-servlet.xml 中定义的 bean 定义? spring-security 配置的流程是什么。据我所知,我了解 intercept-url 标签拦截请求并使用表达式语言检查适当的角色。我无法理解如何通过我提供的身份验证管理器,它在数据库中看起来很合适。

下面是我在 service.xml 中的 userService bean 定义

    <bean name="userService" class="com.qait.cdl.services.impl.UserServiceImpl">
            <property name="userDao" ref="userDao" />
        </bean> 

下面是userService接口

public interface UserService extends UserDetailsService

这个 UserDetailsS​​ervice 来自 springframework

下面是 UserServiceimpl 类

public class UserServiceImpl implements UserService 
 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException 
        UserDetails userDetails = null;
        if(username != null &&  !"".equals(username))
            User user = userDao.get(username);
            if(user != null)
                UserGroupAuthority groupAuthority = userDao.getUserAuthority(user);
                if(groupAuthority != null)
                    Collection<GrantedAuthority> grantedAuthorities = getGrantedAuthorities(groupAuthority.getAuthority());
                    userDetails = new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), 
                            true, true, true, true, grantedAuthorities);
                
            
        
        return userDetails;
    

    @Override
    public Collection<GrantedAuthority> getGrantedAuthorities(String authority) 
        List<GrantedAuthority> grantedAuthorities = new LinkedList<GrantedAuthority>();
        grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_USER"));
        return grantedAuthorities;
    

    @Override
    public UserGroupAuthority getUserAuthority(User user) 
        return userDao.getUserAuthority(user);
    

问题很简单,它没有验证给定的拦截 URL。我在哪里做错了?

【问题讨论】:

为什么您的springSecurityFilterChainweb.xml 中被停用? 是否有必要给“springSecurityFilterChain”,因为我认为 /* 拦截所有传入的请求。但我不想那样。所以,我确实评论了该代码 【参考方案1】:

在您的web.xml 中激活springSecurityFilterChain。它是 Spring Security 的入口点。如果 springSecurityFilterChain 被停用,那么 Spring Security 将永远无法工作。

【讨论】:

但是为什么互联网上到处都有标签/*,这个标签有什么意义 激活springSecurityFilterChain后,它正在工作并且它也在拦截url,但问题是它调用hasRole('ROLE_ADMIN')方法时。当我将 springsecurityconfig 文件更新到以下文件时 它显示了spring的默认jsp页面,用于用户名和密码。我不希望这样,我认为这不是一个好方法,因为用户已经输入了用户名和密码,为什么这样又问了 /* url-pattern 表示在每次请求期间都会调用此过滤器。但这并不意味着每个响应实际上都会由该过滤器本身准备。过滤器实际上会做很多工作(例如检查登录用户是否有权打开实际 URL)。实际请求将由相应的 servlet/控制器准备。 我认为应该是这样,当用户每次登录到我的应用程序时,spring应该在intercept-url上调用hasRole()方法并从我提供的db中检查角色并提取角色基于用户名,如果返回“ROLE_ADMIN”而不是用户应该允许,否则应该显示访问拒绝页面,我将在配置文件中提供 如果它不适合你,那么你有一些配置问题。为 org.springframework.security 包启用调试日志记录并查看您的日志(log4j.logger.org.springframework.security=DEBUG 在 log4j 的情况下)。

以上是关于无法在现有应用程序中集成 Spring Security的主要内容,如果未能解决你的问题,请参考以下文章

现有项目中集成Flutter

KMM 入门在现有工程中集成 KMM

KMM 入门在现有工程中集成 KMM

KMM 入门在现有工程中集成 KMM

iOS项目中集成Flutter的最新适配升级

在 Android 中集成 Flutter