Spring Security-如何使用数据库动态定义拦截URL? [英] Spring Security - how can I define intercept-url dynamically using Database?

查看:158
本文介绍了Spring Security-如何使用数据库动态定义拦截URL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近一直在研究Spring Security,我需要知道如何使用数据库动态定义(在Spring Security中)拦截URL.

我已经在整个互联网上进行了深入研究,在该领域找不到任何独特的教程(当然也很有用).

这就是我的工作:


首先,我实现了FilterInvocationSecurityMetadataSource抽象类:



并将我的security.xml设置为:



我找不到一些问题:
1.我已将<"URL","ROLE">之类的配对插入URL_ACCESS数据库.但是我不确定getAttributes方法是否可以正常工作
2.我是否必须实现在

中使用的所有那些过滤器



3.当用户使用错误的用户名/密码或尝试访问不允许的页面,而不是重定向到login.jsp时,我收到异常消息.为什么会这样?

预先感谢

解决方案

感谢汤姆和罗布的快速回复.

首先,我完全意识到在数据库中存储url模式不是一个好主意".但是,我们正在尝试动态管理所有内容.因此,没有其他选择.

事实证明,我的代码存在一些小问题. 在这里,我一个一个地回答我的每个问题.

  1. 我的getAttributes方法工作正常.但是,还有一种替代方法可以加载url模式. 我可以先将所有url模式及其相应角色分别加载到HashedMap中.在getAttributes方法中,我可以只查找HasehdMap. 简而言之,它是这样的:

    • HashedMap URL访问 = myDBManager.getAllUrlAccess();
      在我的getAttributes方法中,我使用了 url-access 这个东西.
  2. 这个问题已经过修剪! 我试图询问关于springSecurityFilterChain bean中使用的那些过滤器.

    <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
            <security:filter-chain-map path-type="ant">
                <sec:filter-chain pattern="/css/**" filters="none" />
                <sec:filter-chain pattern="/images/**" filters="none" />
                <sec:filter-chain pattern="/login.jsp*" filters="none" />
                <sec:filter-chain pattern="/**"
                    filters="
                securityContextPersistenceFilter,
                logoutFilter,
                authenticationProcessingFilter,
                exceptionTranslationFilter,
                filterSecurityInterceptor" />
            </security:filter-chain-map>
    </bean>
    

  3. 我正在接收异常,因为在authenticationProcessingFilter bean中没有这样的属性. 所以我这样重写它:

    <bean id="authenticationProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
        <property name="filterProcessesUrl" value="/j_spring_security_check" />
        <property name="usernameParameter" value="j_username" />
        <property name="passwordParameter" value="j_password" />
        <property name="authenticationManager" ref="authenticationManager" />   
    </bean>
    

当然,我也必须引入authenticationFailureHandler bean:

<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/index.jsp" />
</bean>

现在我没有收到任何例外.

但这又引出了另一个问题: 我无法理解用户名/密码是否正确或用户名无权访问所请求的页面. 在这两种情况下,都会根据此bean重定向用户:

<bean id="authenticationEntryPoint"
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/login.jsp?error=EntryPoint" />
</bean>

为什么要同时控制这两种情况?

I've been working on a spring security recently and I need to know how I can define intercept-url (in Spring Security) dynamically using a Database.

I've already dug deep the whole internet and I could not find any unique (and of course useful) tutorial in this area.

So here is what I did:


First I implemented FilterInvocationSecurityMetadataSource Abstract class:

public class MyFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {


    public List<ConfigAttribute> getAttributes(Object object) {
        FilterInvocation fi = (FilterInvocation) object;
        String url = fi.getRequestUrl();
        List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();

        attributes = getAttributesByURL(url);

        return attributes;
    }

    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    public List<ConfigAttribute> getAttributesByURL(String inputUrl)
    {
        List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();

        Connection connection = null;
        String url = "jdbc:mysql://173.0.0.22:3306/";
        String dbName = "kheirkhahandb";
        String driverName = "com.mysql.jdbc.Driver";
        String userName = "kheirkhahan";
        String password = "kheirkhahan";
        try{
            Class.forName(driverName).newInstance();
            connection = DriverManager.getConnection(url+dbName, userName, password);
            try{
                Statement stmt = connection.createStatement();
                String selectquery = "select * from URL_ACCESS where URL = '" + inputUrl +"'";
                ResultSet rs = stmt.executeQuery(selectquery);
                while(rs.next()){
                    MyConfigAttribute temp = new MyConfigAttribute();
                    String attr = rs.getString("ACCESS").toString();
                    temp.setAttr(attr);
                    attributes.add(temp);
                }
            }
            catch(SQLException s){
                System.out.println(s);
            }
            connection.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return attributes;
    }



and I set my security.xml as:

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
        <sec:filter-chain-map path-type="ant">
            <sec:filter-chain pattern="/css/**" filters="none" />
            <sec:filter-chain pattern="/images/**" filters="none" />
            <sec:filter-chain pattern="/login.jsp*" filters="none" />
            <sec:filter-chain pattern="/**"
                filters="
            securityContextPersistenceFilter,
            logoutFilter,
            authenticationProcessingFilter,
            exceptionTranslationFilter,
            filterSecurityInterceptor" />
        </sec:filter-chain-map>
    </bean>

    <bean id="securityContextPersistenceFilter"
        class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    </bean>

    <bean id="exceptionTranslationFilter"
        class="org.springframework.security.web.access.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
        <property name="accessDeniedHandler" ref="accessDeniedHandler" />
    </bean>

    <bean id="authenticationEntryPoint"
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/login.jsp?error=entryPoint" />
    </bean>

    <bean id="accessDeniedHandler"
        class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
        <property name="errorPage" value="/login.jsp?error=access_denied" />
    </bean>

    <bean id="authenticationProcessingFilter"
        class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>

    <bean id="filterSecurityInterceptor"
        class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="accessDecisionManager" ref="accessDecisionManager" />
        <property name="securityMetadataSource" ref="myFilterInvocationSecurityMetadataSource" />
    </bean>

    <bean id="myFilterInvocationSecurityMetadataSource" class="com.datx.dao.MyFilterSecurityMetadataSource">
    </bean>

    <bean id="logoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg value="/login.jsp?error=logout" />
        <constructor-arg ref="logoutHandler">
        </constructor-arg>
    </bean>

    <bean id="logoutHandler"
        class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"></bean>
<sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider>
            <sec:jdbc-user-service data-source-ref="dataSource"
                group-authorities-by-username-query="
                                        SELECT acg.ID, acg.GROUP_NAME, a.AUTHORITY_NAME AS AUTHORITY 
                                        FROM ACCESS_GROUPS acg, ACCESS_GROUP_MEMBERSHIP agm, GROUP_AUTHORITIES ga, AUTHORITIES a
                                        WHERE agm.USERNAME = ? and acg.ID = ga.GROUP_ID and acg.ID = agm.GROUP_ID and ga.AUTHORITY_ID = a.ID
                                    "
                users-by-username-query="SELECT USERNAME,PASSWORD,IS_ACTIVE FROM USER where USERNAME = ?"
                authorities-by-username-query="
                                        SELECT ua.USERNAME, a.AUTHORITY_NAME AS AUTHORITY 
                                        FROM USER_AUTHORITIES ua, AUTHORITIES a 
                                        WHERE ua.USERNAME = ? and ua.AUTHORITY_ID = a.ID
                                    " />
        </sec:authentication-provider>
    </sec:authentication-manager>

    <bean id="accessDecisionManager"
        class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <ref bean="roleVoter" />
            </list>
        </property>
    </bean>
    <bean id="roleVoter"
        class="org.springframework.security.access.vote.RoleHierarchyVoter">
        <property name="rolePrefix" value="" />
        <constructor-arg ref="roleHierarchy" />
    </bean>

<bean id="roleHierarchy" class="com.datx.dao.MyRoleHierarchyImpl">
        <property name="roleHierarchyEntryDaoJdbc" ref="RoleHierarchyEntryDaoJdbc" />
    </bean>

</beans>



There are some problems that I cannot find out:
1. I've inserted some pairs like <"URL" , "ROLE"> into URL_ACCESS database. But I'm not sure whether getAttributes method is working fine or not
2. Do I have to implement all those filters that I used in



3. I'm receiving exception when a user uses a wrong username/password or tries to access not-permitted-pages, instead of being redirected to login.jsp. Why is that?

Thanks in advance

解决方案

Thank you both Tom and Rob for your quick replies.

First of all, I'm totally aware of "storing url-patterns in database is not a good idea". However we are trying to manage everything dynamically. So there are no other choices.

As it turned out, there were some minor problems with my code. Here I answer each of my questions one by one.

  1. My getAttributes method is working just fine. But there is an alternative to load url-patterns. I could load all url-patterns and their corresponding roles first into a HashedMap seperately. And in getAttributes method I could just look up the HasehdMap instead. In brief, it'd be like this:

    • HashedMap url-access = myDBManager.getAllUrlAccess();
      And in my getAttributes method I use this url-access thing.
  2. The question is somehow trimmed! I was trying to ask about those filters used in springSecurityFilterChain bean.

    <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
            <security:filter-chain-map path-type="ant">
                <sec:filter-chain pattern="/css/**" filters="none" />
                <sec:filter-chain pattern="/images/**" filters="none" />
                <sec:filter-chain pattern="/login.jsp*" filters="none" />
                <sec:filter-chain pattern="/**"
                    filters="
                securityContextPersistenceFilter,
                logoutFilter,
                authenticationProcessingFilter,
                exceptionTranslationFilter,
                filterSecurityInterceptor" />
            </security:filter-chain-map>
    </bean>
    

  3. I was receiving exceptions because in authenticationProcessingFilter bean there were no such properties. So I re-write it like this:

    <bean id="authenticationProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
        <property name="filterProcessesUrl" value="/j_spring_security_check" />
        <property name="usernameParameter" value="j_username" />
        <property name="passwordParameter" value="j_password" />
        <property name="authenticationManager" ref="authenticationManager" />   
    </bean>
    

and of course I had to introduce authenticationFailureHandler bean this as well:

<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/index.jsp" />
</bean>

Now I'm not receiving any exceptions.

But here arises another question: I cannot understand whether username/password is incorrect or the username does not have access to the requested page. In both cases, the user is redirected according to this bean:

<bean id="authenticationEntryPoint"
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/login.jsp?error=EntryPoint" />
</bean>

Why is it controlling both cases?

这篇关于Spring Security-如何使用数据库动态定义拦截URL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆