【问题标题】:how to use Spring security with Custom java class/ custom spring framework's class?如何将 Spring 安全性与自定义 java 类/自定义 spring 框架的类一起使用?
【发布时间】:2014-03-19 20:39:58
【问题描述】:

我的要求如下:

在我们的应用程序中,用户的凭据首次根据数据库进行验证(不使用 Spring Security,因为它是一个遗留应用程序)。如果用户是有效用户,他将登录到应用程序。一旦用户登录到应用程序,他就可以拨打很少的休息电话。现在,我想在进行任何休息调用之前再次使用 Spring Security 验证用户的凭据。在这里,挑战是我们不应该重新设计数据库模式。我们需要使用一个存储过程来验证用户。如果身份验证失败,此特定存储过程将返回错误消息,否则不返回任何内容。在这种情况下没有定义角色。只是使用存储过程的简单身份验证。现在,我想通过 spring security 来完成这一切。可能正在编写一个 java 类/自定义 spring 框架的类,其中调用存储过程并在 spring 安全配置文件中使用该类。有人可以建议如何开始吗?

我已经实现了 AuthenticationProvider。以下是*security.xml。

  <http auto-config="true"  use-expressions="true">
    <intercept-url pattern="/rest/*" access="permitAll"></intercept-url>
</http>

    <authentication-manager >
    <authentication-provider ref="csAuthenticationProvider" />
</authentication-manager>

但是,安全框架正在寻找角色。就我而言,没有定义角色。前面说了,用户第一次认证,没有使用spring框架。如果用户想要进行任何休息调用,spring security 需要重新对用户进行身份验证。这并不意味着用户需要重新输入凭据。用户的凭据在其余调用/请求中可用,因为他已经过身份验证。唯一需要做的是我需要通过使用请求来使用凭据并使用存储过程重新验证。当然,使用 AuthenticationProvider 可能是个好主意,但是 authenticate(Authentication authentication) 方法的参数“Authentication authentication”对我没有用,因为我需要再次调用自己的存储过程调用。我暂时没有使用Authentication对象,而是使用authenticate()方法中的存储过程调用代码。但是,奇怪的是,authenticate() 方法没有被调用。我很惊讶,也很困惑。有没有人知道我在哪里做错了?

【问题讨论】:

  • 如果有人可以分享我的问题的伪代码,那就太好了。
  • 请更具体地描述你在做什么。您说“安全框架正在寻找角色”。那是什么意思?实际调用的是什么代码?还要说明如果没有可用的凭据并且您不希望用户提供任何凭据,您希望 Spring Security 如何对用户进行身份验证。如果您希望只使用与他们登录时相同的 HTTP 会话,那么当您对用户进行身份验证时,您需要创建一个 Spring Security 可以用于未来请求的安全上下文。
  • Luke,谢谢!,“安全框架正在寻找角色”:意思是根据我的要求,不需要验证角色。当用户第一次登录时,用户输入的凭据存储在请求对象中。我需要使用这些凭据并使用spring security(通过存储过程调用)重新进行身份验证。我可以在用户登录时使用相同的 HTTP 会话。请指导我如何获取相同的 HTTP 会话、创建 Spring Security 上下文并根据上述要求重新进行身份验证。如果能分享一些伪代码就好了。

标签: java spring security spring-security


【解决方案1】:

听起来您需要实现一个身份验证提供程序。这是一个非常简单的示例,我认为您可以调整它来调用您的存储过程。

http://danielkaes.wordpress.com/2013/02/20/custom-authentication-provider-in-spring/

【讨论】:

  • 感谢您的快速回复。我会看看您发布的链接。
  • 能否请您看一下编辑后的内容并提出任何想法?
【解决方案2】:

你可以实现自己的 UserDetailsS​​ervice 并配置 spring 来使用它。

<security:authentication-manager>
    <security:authentication-provider user-service-ref="userDetailsServiceImpl"/>
</security:authentication-manager>

【讨论】:

  • 感谢您的快速回复。最初,我也这么认为。如果我们实现 UserDetailsS​​ervice,我们需要重写 loadUserByUsername(String username)。但是,在某些方面,UserDetailsS​​ervice 类没有被调用。如果你想看,我会把代码贴出来。
  • 查看我在 rhinds 问题中的评论 - UserDetailsS​​ervice 不进行身份验证(请参阅this FAQ。如果您想封装自己的身份验证代码,最好直接实现 AuthenticationProvider。
  • 感谢卢克的回复。我将尝试按照您所说的实现 AuthenticationProvider 并在发现任何问题时通知您。
【解决方案3】:

您需要创建一个自定义的 UserDetailsS​​ervice 实现,它将检查数据库。

下面是一个 UserDetailsS​​ervice 实现的例子:

@Service("userService")
public class UserDetailsServiceImpl implements UserDetailsService, InitializingBean {

    @Autowired
    private AccountService accountService;

    public void afterPropertiesSet() throws Exception {
    }

    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        username = username.toLowerCase();
        try {
            Account account = accountService.loadUserAccountByEmail(username);
            if (account == null) {
                throw new UsernameNotFoundException("Could not find email: " + username + "in the DB.");
            }

            List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
            for (Role r : account.getRoles()) {
                auths.add(new SimpleGrantedAuthority(r.getRole()));
            }
            ApplicationUser user = null;
            try {
                user = new ApplicationUser(new Long(account.getId()), username, account.getPassword(), true, true, true, true, auths);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return user;
        } catch (Exception e) {
            e.printStackTrace();
            throw new UsernameNotFoundException(username + "not found", e);
        }
    }

}

我在代码中这样配置:

@Override
     protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
         auth
            .userDetailsService(userDetailsServiceImpl)
            .passwordEncoder(bCryptPasswordEncoder());
     }

(您还可以看到我写的一篇关于从 xml 切换到 @annotation config 的博文,以在此处引用该项目:http://automateddeveloper.blogspot.co.uk/2014/02/spring-4-xml-to-annotation-configuration.html

【讨论】:

  • 要求是使用存储过程进行身份验证。 UserDetailsS​​ervice 不执行身份验证,因此不是合适的选项。
  • 啊,是的。你是对的 - 我把它读作存储过程只是抓取用户数据 - 掩盖了关于在数据库中进行实际身份验证的内容。
  • 卢克,你能看看编辑的内容并提出任何想法吗?
猜你喜欢
  • 2014-10-23
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 2018-04-12
  • 1970-01-01
  • 2019-03-29
相关资源
最近更新 更多