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

查看:62
本文介绍了在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是硬编码的.我想知道是否有一种方法可以动态创建新的ROLES和PERMISSIONS,而不是硬编码.

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书,位于第210页左右.希望他们有章号!).因此,您现在需要做的是继承WebSecurityExpressionRoot的子类,并引入一个新的方法isAllowdForUserPages1To3.然后,您需要继承DefaultWebSecurityExpressionHandler的子类并修改createEvaluationContext方法,以便其第一个请求StandartEvaluationContext调用super(您需要将结果强制转换为StandartEvaluationContext).然后,使用新的CustomWebSecurityExpressionRoot实现替换StandartEvaluationContext中的rootObject.那是困难的部分!然后,您需要用新的子类DefaultWebSecurityExpressionHandler替换xml配置中expressionVoter(WebExpressionVoter)的expressionHandler属性. (这很烂,因为您首先需要明确地编写很多安全配置,因为您不能直接从安全名称空间访问它们.)
  • 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天全站免登陆