【问题标题】:SpringSecurity - Custom automatic authenticationSpringSecurity - 自定义自动认证
【发布时间】:2012-09-10 19:26:52
【问题描述】:

这是我的场景:

  • 网络应用为许多应用执行某种 SSO
  • 登录后的用户点击链接后,应用会向相应的应用发布用户信息(姓名、密码 [无用]、角色)
  • 我正在其中一个应用程序上实现 SpringSecurity 以从其强大功能(会话中的权限、其类提供的方法等)中受益

所以,我需要开发一个 自定义过滤器 - 我猜 - 能够通过自定义 DetailsUserService 从请求中检索用户信息,从数据库中检索,进一步有关用户的信息(电子邮件等),然后根据从请求中检索到的角色对该用户执行身份验证。

我正在查看Pre-Authentication 过滤器,但我不确定它是否是正确的选择。当主体已经在会话中时,似乎应该使用这些对象,由一些先前的身份验证机制提出(对吗?)。

我认为,一旦确定了正确的过滤器,我应该需要执行以下操作:

GrantedAuthority[] ga= new GrantedAuthority[1];
ga[0] = new GrantedAuthorityImpl(myUser.getRole());

SecurityContext sc = SecurityContextHolder.getContext();
Authentication a = new UsernamePasswordAuthenticationToken(userName, userPwd, ga);
a = authenticationManager.authenticate(a);
sc.setAuthentication(a);

这是解决我的问题的正确方向吗?你有什么建议可以帮助我找到缺少的东西吗?

谢谢大家,

卢卡

补充:

嗨,Xearxess!很抱歉再次打扰您,但似乎根据 SpringSecurity 2.0.4 翻译您的代码比我想象的要困难:S 问题是 XML ......我尝试了不同的配置,但我总是遇到命名空间问题,缺少属性等等……

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

    <security:http>
        <security:intercept-url pattern="/**" access="isAuthenticated()" />
        <security:logout logout-url="/logout" logout-success-url="http://milan-ias-vs.usersad.everis.int/DMTest/" invalidate-session="true" />
        <security:custom-filter position="PRE_AUTH_FILTER" ref="preAuthenticatedProcessingFilter" />
    </security:http>

    <bean id="preAuthenticatedProcessingFilter" class="it.novartis.ram.authentication.PreAuthenticatedProcessingFilter">
        <custom-filter position="PRE_AUTH_FILTER"/>
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>

    <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="preAuthenticatedUserDetailsService">
            <bean class="it.novartis.ram.authentication.PreAuthenticatedUserDetailsService" />
        </property>
    </bean>

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="preauthAuthProvider" />
    </security:authentication-manager>

</beans>

引用 CUSTOM-FILTER 元素的 2 行是两次不同的尝试,它们都被标记为错误。如何将过滤器的位置指定为属性?

身份验证管理器定义上的身份验证提供程序引用也被标记为错误。我想我也需要像属性一样指定它,对吧?

希望你能给我最后一击;) 再次感谢您,

卢卡

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    为了完整起见,在 Spring Security 4 中进行了轻微更改。例如,强烈建议使用 Java 配置。这样就更容易与 Spring Boot 集成。

    它遵循等效于上述答案中给出的 XML 配置的 Java 配置。

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.addFilterBefore(customAuthFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authenticationProvider(preauthAuthProvider())
                .authorizeRequests()
                .anyRequest().authenticated();
        }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(preauthAuthProvider());
        }
    
        @Bean
        public PreAuthenticatedAuthenticationProvider preauthAuthProvider() {
            PreAuthenticatedAuthenticationProvider preauthAuthProvider =
                new PreAuthenticatedAuthenticationProvider();
                    preauthAuthProvider.setPreAuthenticatedUserDetailsService(
                        userDetailsServiceWrapper());
            return preauthAuthProvider;
        }
    
        @Bean
        public OnlyRolesPreAuthenticatedUserDetailsService userDetailsServiceWrapper() {
            OnlyRolesPreAuthenticatedUserDetailsService service =
                new MyPreAuthenticatedUserDetailsService();
            return service;
        }
    
        @Bean
        public MyPreAuthenticatedProcessingFilter customAuthFilter() throws Exception {
            MyPreAuthenticatedProcessingFilter filter = new MyPreAuthenticatedProcessingFilter();
            filter.setAuthenticationManager(authenticationManager());
            return filter;
        }
    }
    

    我认为上面的代码是值得的,因为互联网上的示例非常基础,而 Spring 文档缺乏这样的细节。

    【讨论】:

    • 非常感谢!我在任何地方都没有找到关于 java 配置的解释
    • 很高兴为您提供帮助。
    • 我想知道将过滤器放入 addFilterAfter/Before() 方法的正确方法是什么?应该有 bean 还是 new 运算符?
    • 非常感谢,这正是我想要的
    【解决方案2】:

    是的,预身份验证方案正是您正在寻找的。

    似乎那些对象应该在主体时使用 已经在会话中,由一些先前的身份验证机制放置 (对吗?)。

    并非如此,您可以根据需要使用预身份验证从请求中创建PreAuthenticatedAuthenticationToken。只需do few things I described in another question

    先扩展AbstractPreAuthenticatedProcessingFilter,从请求中获取用户名和角色:

    public class MyPreAuthenticatedProcessingFilter
        extends AbstractPreAuthenticatedProcessingFilter {
    
      public MyPreAuthenticatedProcessingFilter(
          AuthenticationManager authenticationManager) {
        setAuthenticationDetailsSource(new MyAuthenticationDetailsSource());
      }
    
      @Override
      protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        return "Anonymous";
      }
    
      @Override
      protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
        return "N/A";
      }
    
      public static class MyAuthenticationDetailsSource implements 
          AuthenticationDetailsSource<HttpServletRequest, MySessionUserDetails> {
        // roles probably should be encrypted somehow
        static final String ROLES_PARAMETER = "pre_auth_roles";
    
        @Override
        public MySessionUserDetails buildDetails(HttpServletRequest req) {
          // create container for pre-auth data
          return new MySessionUserDetails(req.getParameter(ROLES_PARAMETER));
        }
      }
    }
    

    MySessionUserDetails 类将带有角色的 spring 拆分为 SimpleGrantedAuthority 列表或任何其他 GrantedAuthority 实现。另外,推荐使用 List 并且优于 GrantedAuthority[]

    二、实现AuthenticationUserDetailsService

    public class MyPreAuthenticatedUserDetailsService implements 
        AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
    
      @Override
      public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token)
          throws UsernameNotFoundException {
        MySessionUserDetails sessionUserDetails =
            (MySessionUserDetails) token.getDetails();
        List<GrantedAuthority> authorities = sessionUserDetails.getAuthorities();
        return new User(token.getName(), "N/A", true, true, true, true, authorities);
      }
    }
    

    然后在您的 XML 中将块连接在一起:

    <security:http use-expressions="true">
      <security:intercept-url pattern="/**" access="isAuthenticated()" />
      <security:custom-filter position="PRE_AUTH_FILTER"
          ref="myPreAuthenticationFilter" />
    </security:http>
    
    <bean id="myPreAuthenticationFilter"
        class="com.example.MyPreAuthenticatedProcessingFilter">
      <property name="authenticationManager" ref="authenticationManager" />
    </bean>
    
    <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
      <property name="preAuthenticatedUserDetailsService">
        <bean class="com.example.MyPreAuthenticatedUserDetailsService" />
      </property>
    </bean>
    
    <security:authentication-manager alias="authenticationManager">
      <security:authentication-provider ref="preauthAuthProvider" />
    </security:authentication-manager>
    

    瞧!您应该已验证 User 主体以在您的应用程序中使用。

    我在这里编写的代码需要 Spring Security 3.1,如果您即将使用它,我强烈建议您使用它(它确实需要 Spring 3.0.7+)。另外,Spring Security reference manual 是你的朋友!

    【讨论】:

    • 非常感谢 Xaerxess!不幸的是,我们坚持使用 Spring 2.5.6 和 Spring Security 2.0.4,但您的建议会对我有所帮助;)
    • 很遗憾,Spring 3 更好,通用并且有很好的文档。但是上面的大量代码可以向后移植到 2.X(例如没有泛型)。
    • 确实可惜!但是你写的代码会对我有所帮助。再次感谢您,与您的宝宝度过愉快的时光;)
    • 很高兴我能帮上忙!她现在快 2 岁了,我必须更新照片;)
    • 我终于明白了!解决了 Spring3 的问题(Oracle OC4J 上 xml 解析器的类加载问题)并将您的配置用作模板:现在一切正常!只需要添加 AuthenticationEntryPoint 的实现。再次感谢!下午我会发布完整的配置以帮助像我这样的新手。
    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 2016-06-22
    • 1970-01-01
    • 2019-05-02
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多