Вопрос по spring-security, spring – Spring Security - как я могу определить intercept-url динамически, используя базу данных?

3

Недавно я работал над защитой Spring, и мне нужно знать, как я могу динамически определять URL-адрес перехвата (в Spring Security) с использованием базы данных.

Я уже глубоко изучил весь Интернет и не смог найти ни одного уникального (и, конечно, полезного) учебника в этой области.

Итак, вот что я сделал:

Сначала я реализовал класс FilterInvocationSecurityMetadataSource Abstract:

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;
    }


и я установил свой security.xml как:

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


Есть некоторые проблемы, которые я не могу выяснить:
1. Я вставил несколько пар, таких как & lt; & quot; URL & quot; , "РОЛЬ" & gt; в базу данных URL_ACCESS. Но я не уверен, что метод getAttributes работает нормально или нет
2. Должен ли я реализовать все те фильтры, которые я использовал в



3. Я получаю исключение, когда пользователь использует неправильное имя пользователя / пароль или пытается получить доступ к недопустимым страницам вместо того, чтобы быть перенаправленным на login.jsp. Это почему?

заранее спасибо

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

Ваш Ответ

2   ответа
4

Часто задаваемые вопросы об этом, чтобы убедиться, что вы действительно хотите это сделать. КакТом ссылаясь на это, как правило, не рекомендуется размещать такую информацию в базе данных.

С точки зрения того, работает ли / почему ваш текущий код, трудно сказать без подробностей. Например, какие ошибки вы видите в журналах? Вопрос в # 2, кажется, не завершен. Что говорят журналы Spring Security?

Если мы будем придерживаться этого плана, я бы продолжил полностью использовать конфигурацию пространства имен ииспользовать BeanPostProcessor (как обсуждено в FAQ) поменятьFilterInvocationServiceSecurityMetadataSource, Реализация может выглядеть примерно так:

public class FilterInvocationServiceSecurityMetadataSourceBeanPostProcessor 
    implements BeanPostProcessor { 
    private FilterInvocationServiceSecurityMetadataSource metadataSource;

    public void setMetadataSource(FilterInvocationServiceSecurityMetadataSource metadataSource) {
        this.metadataSource = metadataSource;
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) { 
        if(bean instanceof FilterInvocationSecurityMetadataSource) { 
            return metadataSource; 
        } 
        return bean; 
    } 

    public Object postProcessAfterInitialization(Object bean, String beanName) { 
        return bean; 
    } 
}

Тогда ваш обычайFilterInvocationServiceSecurityMetadataSource может быть указан в конфигурации Spring вместе сFilterInvocationServiceSecurityMetadataSourceBeanPostProcessor.

<bean id="fiMds" class="FilterInvocationServiceSecurityMetadataSourceBeanPostProcessor">
  <property name="metadataSource">
    <bean id="myFilterInvocationSecurityMetadataSource" class="com.datx.dao.MyFilterSecurityMetadataSource"/>
  </property>
</bean>
2

Прежде всего, я полностью осведомлен о том, что «сохранение шаблонов url в базе данных не является хорошей идеей». Однако мы стараемся все динамически управлять. Так что других вариантов нет.

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

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.

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>

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>

и, конечно, я должен был представить bean-компонент authenticationFailureHandler:

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

Сейчас я не получаю никаких исключений.

Но здесь возникает другой вопрос: Я не могу понять, является ли имя пользователя / пароль неправильным или имя пользователя не имеет доступа к запрашиваемой странице. В обоих случаях пользователь перенаправляется в соответствии с этим компонентом:

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

Почему он контролирует оба случая?

Вы смогли решить эту проблему?
Да. У меня сейчас два разных класса дляaccess denied а такжеentry point, Для бывшего я бросаю403 исключение, и для последнего пользователь перенаправляется на страницу. Все, что мне нужно было сделать, это использовать другойaccess denied exception handlerи обрабатывать403 ответ нашего интерфейса. Matin Kh

Похожие вопросы