Grails自定义AuthenticationProvider

为了加强我们新Grails应用程序中的安全性,我着手实现了Spring Security Plugin 。 使用标准的用户名/密码进行安装和运行很简单,因为所有这些都由插件自动连接。 这解决了我一半的问题,但是我们还需要支持SAML身份验证,并且没有明确的示例来说明如何实现。 如果有人有类似的要求,我想分享一下我的作品。 我将不专注于SAML细节,而是关注如何在grails中构建任何自定义身份验证提供程序。
您可以通过扩展AbstractAuthenticationProcessingFilter并将其注册到Spring来将URL映射到过滤器。 然后,您可以提供该URL进行自定义身份验证。 就我而言,它看起来像这样:
class SamlAuthenticationFilter extends AbstractAuthenticationProcessingFilter  {

    public SamlAuthenticationFilter() {
        super("/somecustomauth")
    }

    @Override
    Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod())
        }

        String accessToken = request.getParameter("sometoken")
        return this.getAuthenticationManager().authenticate(new SamlAuthenticationToken(accessToken));
    }

}

然后将过滤器与身份验证提供程序一起设置为Spring Bean,稍后将进行讨论:

import SamlAuthenticationFilter
import SamlAuthenticationProvider

beans = {
    samlAuthenticationFilter(SamlAuthenticationFilter) {
        authenticationManager = ref('authenticationManager')
        sessionAuthenticationStrategy = ref('sessionAuthenticationStrategy')
        authenticationSuccessHandler = ref('authenticationSuccessHandler')
        authenticationFailureHandler = ref('authenticationFailureHandler')
        rememberMeServices = ref('rememberMeServices')
        authenticationDetailsSource = ref('authenticationDetailsSource')
    }

    samlAuthenticationProvider(SamlAuthenticationProvider) {
        sAMLAuthenticationService = ref('SAMLAuthenticationService')
        sAMLSettingsService = ref('SAMLSettingsService')
        userDetailsService = ref('userDetailsService')
        passwordEncoder = ref('passwordEncoder')
        userCache = ref('userCache')
        saltSource = ref('saltSource')
        preAuthenticationChecks = ref('preAuthenticationChecks')
        postAuthenticationChecks = ref('postAuthenticationChecks')
    }
}

然后,该bean在Bootstrap中注册为过滤器:

import org.codehaus.groovy.grails.plugins.springsecurity.SecurityFilterPosition
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

class BootStrap {

    def init = { servletContext ->
        SpringSecurityUtils.clientRegisterFilter('samlAuthenticationFilter', SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)
    }

    def destroy = {
    }
}

我们还需要创建由过滤器和身份验证提供程序使用的Token类:

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.userdetails.UserDetails

class SamlAuthenticationToken extends UsernamePasswordAuthenticationToken {

    String token

    public SamlAuthenticationToken(String token) {
        super(null, null);
        this.token = token;
    }

    public SamlAuthenticationToken(UserDetails principal, String samlResponse) {
        super(principal, samlResponse, principal.getAuthorities())
    }

}

最后是AuthenticationProvider本身:

import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.Authentication
import sonicg.authentication.SAMLAuthenticationService

class SamlAuthenticationProvider extends DaoAuthenticationProvider {

    @Override
    Authentication authenticate(Authentication authentication) {
        def token = (SamlAuthenticationToken) authentication

        def user = // define user if credentials check out

        if (user){
            def userDetails = userDetailsService.loadUserByUsername(user.username)
            def token1 = new SamlAuthenticationToken(userDetails, token.samlResponse)
            return token1
        }else{
            return null
        }

    }

    @Override
    public boolean supports(Class authentication) {
        return (SamlAuthenticationToken.class.isAssignableFrom(authentication));
    }
}

最后一个难题是告诉Spring在Config.groovy中的其他三个标准之前尝试使用此身份验证提供程序:

grails.plugins.springsecurity.providerNames = [
        'samlAuthenticationProvider',
        'daoAuthenticationProvider',
        'anonymousAuthenticationProvider',
        'rememberMeAuthenticationProvider']
在这种情况下,自定义过滤器优先是很重要的,因为它的Token是UsernamePasswordAuthenticationToken的子类。 如果DAO提供者是第一个,它将在我们的过滤器获得机会之前尝试对自定义令牌进行身份验证。
而已! 希望这对某人有用。 这只是一个初稿,也许一旦安全要求发展,我就可以完善实现并分享我学到的知识。

参考:来自我们的JCG合作伙伴 Kali Kallin的Grails自定义AuthenticationProviderKallin Nagelberg进入西方博客的过程中。


翻译自: https://www.javacodegeeks.com/2012/07/grails-custom-authenticationprovider.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值