在 Spring Security 3 中动态创建新角色和权限 [英] Creating New Roles and Permissions Dynamically in Spring Security 3

查看:17
本文介绍了在 Spring Security 3 中动态创建新角色和权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Struts 2 + Spring IOC 项目中使用 Spring Security 3.

I am using Spring Security 3 in Struts 2 + Spring IOC project.

我在我的项目中使用了自定义过滤器、身份验证提供程序等.

I have used Custom Filter, Authentication Provider etc. in my Project.

你可以在这里看到我的 security.xml

You can see my security.xml here

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security-3.1.xsd">


<global-method-security pre-post-annotations="enabled">
        <expression-handler ref="expressionHandler" />
</global-method-security>

<beans:bean id="expressionHandler"
        class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" >
    <beans:property name="permissionEvaluator" ref="customPermissionEvaluator" />
</beans:bean>

<beans:bean class="code.permission.MyCustomPermissionEvaluator" id="customPermissionEvaluator" />

<!-- User Login -->

  <http auto-config="true" use-expressions="true" pattern="/user/*" >
<intercept-url pattern="/index.jsp" access="permitAll"/>
<intercept-url pattern="/user/showLoginPage.action" access="permitAll"/>
<intercept-url pattern="/user/showFirstPage" access="hasRole('ROLE_USER') or hasRole('ROLE_VISIT')"/>
<intercept-url pattern="/user/showSecondUserPage" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/user/showThirdUserPage" access="hasRole('ROLE_VISIT')"/>
<intercept-url pattern="/user/showFirstPage" access="hasRole('ROLE_USER') or hasRole('ROLE_VISIT')"/>
<form-login login-page="/user/showLoginPage.action" />
<logout invalidate-session="true"
        logout-success-url="/"
        logout-url="/user/j_spring_security_logout"/>
<access-denied-handler ref="myAccessDeniedHandler" />

  <custom-filter before="FORM_LOGIN_FILTER" ref="myApplicationFilter"/>
  </http>

    <beans:bean id="myAccessDeniedHandler" class="code.security.MyAccessDeniedHandler" />

    <beans:bean id="myApplicationFilter" class="code.security.MyApplicationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager"/>
        <beans:property name="authenticationFailureHandler" ref="failureHandler"/>
        <beans:property name="authenticationSuccessHandler" ref="successHandler"/>
    </beans:bean>

    <beans:bean id="successHandler"
  class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
      <beans:property name="defaultTargetUrl" value="/user/showFirstPage">   </beans:property>
    </beans:bean>

     <beans:bean id="failureHandler"
  class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
      <beans:property name="defaultFailureUrl" value="/user/showLoginPage.action?login_error=1"/>
    </beans:bean>

    <beans:bean id= "myUserDetailServiceImpl" class="code.security.MyUserDetailServiceImpl">
    </beans:bean>

     <beans:bean id="myAuthenticationProvider" class="code.security.MyAuthenticationProvider">
        <beans:property name="userDetailsService" ref="myUserDetailServiceImpl"/>

    </beans:bean>

 <!-- User Login Ends -->

 <!-- Admin Login -->

    <http auto-config="true" use-expressions="true" pattern="/admin/*" >
    <intercept-url pattern="/index.jsp" access="permitAll"/>
    <intercept-url pattern="/admin/showSecondLogin" access="permitAll"/>
    <intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')"/>
    <form-login login-page="/admin/showSecondLogin"/>
    <logout invalidate-session="true"
        logout-success-url="/"
        logout-url="/admin/j_spring_security_logout"/>

    <access-denied-handler ref="myAccessDeniedHandlerForAdmin" />
    <custom-filter before="FORM_LOGIN_FILTER" ref="myApplicationFilterForAdmin"/> 
</http>

<beans:bean id="myAccessDeniedHandlerForAdmin" class="code.security.admin.MyAccessDeniedHandlerForAdmin" />

  <beans:bean id="myApplicationFilterForAdmin" class="code.security.admin.MyApplicationFilterForAdmin">
        <beans:property name="authenticationManager" ref="authenticationManager"/>
        <beans:property name="authenticationFailureHandler" ref="failureHandlerForAdmin"/>
        <beans:property name="authenticationSuccessHandler" ref="successHandlerForAdmin"/>
   </beans:bean>

    <beans:bean id="successHandlerForAdmin"
  class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    </beans:bean>

    <beans:bean id="failureHandlerForAdmin"
  class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
       <beans:property name="defaultFailureUrl" value="/admin/showSecondLogin?login_error=1"/>
     </beans:bean>

        <authentication-manager alias="authenticationManager">
    <authentication-provider ref="myAuthenticationProviderForAdmin" />
    <authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>

<beans:bean id="myAuthenticationProviderForAdmin" class="code.security.admin.MyAuthenticationProviderForAdmin">
    <beans:property name="userDetailsService" ref="userDetailsServiceForAdmin"/>
</beans:bean>

<beans:bean id= "userDetailsServiceForAdmin" class="code.security.admin.MyUserDetailsServiceForAdminImpl">
</beans:bean>

 <!-- Admin Login Ends -->

<beans:bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
    <beans:property name="basenames">
        <beans:list>
            <beans:value>code/security/SecurityMessages</beans:value>
        </beans:list>
    </beans:property>            
</beans:bean>

直到现在你可以看到,我提到的 url-pattern 是硬编码的.我想知道是否有办法动态创建新角色和权限,而不是硬编码.

Uptill now you can see, url-pattern I have mentioned is hard coded. I wanted to know if there is a way to create new ROLES and PERMISSIONS dynamically, not hard coded.

比如创建新的角色和权限并将它们保存到数据库,然后从数据库访问.我在网上搜索过,但我无法找到如何向代码添加新条目.

Like creating new roles and permissions and saving them to database and then accessing from database. I have searched on net, but I am not able to find out how to add new entries to code.

推荐答案

所以这些至少是两个问题:

So these are at least two questions:

  • 如何使授予的权限/特权/角色具有动态性?
  • 如何使 URL 的访问限制动态化?

我不会详细回答这个问题,因为我相信这个主题已经讨论得够多了.

最简单的方法是将完整的用户信息(登录名、密码和角色)存储在数据库中(3 个表:User、Roles、User2Roles)并使用 JdbcDetailService.您可以在 xml 配置中很好地配置两个 SQL 语句(用于身份验证和授予角色).

The easiest way would be to store the complete user information (login, password and roles) in a database (3 Tables: User, Roles, User2Roles) and use the JdbcDetailService. You can configure the two SQL Statements (for authentication and for granting the roles) very nicely in your xml configuration.

但是随后用户需要注销并登录才能获得这些新角色.如果这是不可接受的,您还必须操作当前登录用户的角色.它们存储在用户会话中.我想最简单的方法是在 spring 安全过滤器链中添加一个过滤器,如果需要更改它们,它会更新每个请求的角色.

But then the user needs to logout and login to get these new Roles. If this is not acceptable, you must also manipulate the Roles of the current logged in user. They are stored in the users session. I guess the easiest way to do that is to add a filter in the spring security filter chain that updates the Roles for every request, if they need to be changed.

这里有最后两种方法:

  • 入侵FilterSecurityInterceptor 并更新securityMetadataSource,所需的角色应该存储在那里.至少你必须操作方法的输出 DefaultFilterInvocationSecurityMetadataSource#lookupAttributes(String url, String method)
  • 另一种方法是对 access 属性使用其他表达式,而不是 access="hasRole('ROLE_USER')".示例:access="isAllowdForUserPages1To3".当然,您必须创建该方法.这称为自定义 SpEL 表达式处理程序"(如果您有 Spring Security 3 Book 大约在第 210 页.希望他们有章节号!).所以你现在需要做的是继承WebSecurityExpressionRoot 并引入一个新方法isAllowdForUserPages1To3.然后你需要继承DefaultWebSecurityExpressionHandler 并修改createEvaluationContext 方法,使其第一个请求StandartEvaluationContext 调用super(你需要将结果转换为StandartEvaluationContext).然后,使用新的 CustomWebSecurityExpressionRoot 实现替换 StandartEvaluationContext 中的 rootObject.这是最难的部分!然后,您需要将 xml 配置中 expressionVoter (WebExpressionVoter) 的 expressionHandler 属性替换为新的子类 DefaultWebSecurityExpressionHandler.(这很糟糕,因为您首先需要明确地编写大量安全配置,因为您无法直接从安全命名空间访问它们.)
  • Hacking into the FilterSecurityInterceptor and updating the securityMetadataSource, the needed Roles should be stored there. At least you must manipulate the output of the method DefaultFilterInvocationSecurityMetadataSource#lookupAttributes(String url, String method)
  • The other way would be using other expressions for the access attribute instead of access="hasRole('ROLE_USER')". Example: access="isAllowdForUserPages1To3". Of course you must create that method. This is called a "custom SpEL expression handler" (If you have the Spring Security 3 Book it's around page 210. Wish they had chapter numbers!). So what you need to do now is to subclass WebSecurityExpressionRoot and introduce a new method isAllowdForUserPages1To3. Then you need to subclass DefaultWebSecurityExpressionHandler and modify the createEvaluationContext method so that its first request StandartEvaluationContext calls super (you need to cast the result to StandartEvaluationContext). Then, replace the rootObject in the StandartEvaluationContext using your new CustomWebSecurityExpressionRoot implementation. That's the hard part! Then, you need to replace the expressionHandler attribute of the expressionVoter (WebExpressionVoter) in the xml configuration with your new subclassed DefaultWebSecurityExpressionHandler. (This sucks because you first need to write a lot of security configuration explicity as you can't access them directly from the security namespace.)

这篇关于在 Spring Security 3 中动态创建新角色和权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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