【问题标题】:Spring security : handling SSO and DB usersSpring security:处理 SSO 和 DB 用户
【发布时间】:2016-03-20 02:09:46
【问题描述】:

我有两种不同类型的用户。

  1. SSO 用户
  2. 数据库用户。

SSO 用户可能已经通过不同系统的身份验证,而 DB 用户应该通过我们的系统进行身份验证。我可以配置 Spring 安全性来处理这种情况,我可以为某些用户说提示登录页面,而不提示某些用户。

假设对于 SSO 用户,我可以在请求标头中获取用户 ID,而当 DB 访问应用程序时,请求标头中没有用户 ID。我该如何处理这种情况?

我可以通过扩展 DaoAuthenticationProvider 的身份验证方法来覆盖它,然后在某些参数上的页面决定对用户进行身份验证还是有其他方法?我可以向身份验证类添加任何信息吗

这是我尝试过的

安全配置 java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;


    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
        builder.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder())
                .usersByUsernameQuery("select username,password, enabled from users where username=?")
                .authoritiesByUsernameQuery("select username, role from user_roles where username=?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic()
        .and().addFilterBefore(new UserTypeFilter(), BasicAuthenticationFilter.class);
    }

    public PasswordEncoder passwordEncoder() {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }

    /*
     * @Bean public MethodSecurityInterceptor methodSecurityService() { return
     * new MethodSecurityInterceptor(); }
     */

     @Bean(name="myAuthenticationManager")
       public AuthenticationManager authenticationManagerBean() throws Exception {
           return super.authenticationManagerBean();
       }

     @Bean
        public ExceptionTranslationFilter exceptionTranslationFilter() {
            ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(
                    new Http403ForbiddenEntryPoint());
            AccessDeniedHandlerImpl accessDeniedHandlerImpl = new AccessDeniedHandlerImpl();
            accessDeniedHandlerImpl.setErrorPage("/exception");
            exceptionTranslationFilter
                    .setAccessDeniedHandler(accessDeniedHandlerImpl);
            exceptionTranslationFilter.afterPropertiesSet();
            return exceptionTranslationFilter;
        }

     @Bean
     public UserTypeFilter authenticationFilter() throws Exception {
         UserTypeFilter authFilter = new UserTypeFilter();
         authFilter.setAuthenticationManager(authenticationManager());
         return authFilter;
     }
}

我的自定义 AbstractAuthenticationProcessingFilter

public class UserTypeFilter extends AbstractAuthenticationProcessingFilter {

    private static final String INTERCEPTOR_PROCESS_URL = "/index";

    @Autowired
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

    public UserTypeFilter() {
        super(INTERCEPTOR_PROCESS_URL);
    }

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        System.out.println(" BASIC AUTHENTICATION FILTER");
        String userId = request.getHeader("USERID");
        if (userId == null) {
            System.out.println(" THROWING EXCEPTION FILTER");
            throw new PreAuthenticatedCredentialsNotFoundException("USERID param not found");
        }
        return null;
    }

}

我的控制器

@Controller
public class MainController {


    @RequestMapping(value = { "/index" }, method = RequestMethod.GET)
    public ModelAndView index() {

        ModelAndView model = new ModelAndView();
        model.addObject("message", "This is test page!");
        model.setViewName("dummy");

        return model;

    }

}

控件转到我的自定义过滤器,然后在引发异常但未调用 ExceptionTranslationFilter 时

我是否正确配置了 httpsecurity 我是否正确配置了我的自定义过滤器 我是否配置了 ExceptionTranslation 过滤器 我有什么遗漏吗

【问题讨论】:

  • 你有没有想过在 springsecurityfilterchain 中添加过滤器?
  • 所以请求头中有一个userId。是否有任何密码,或者只要 userId 引用存在的用户,您是否认为请求有效?如何确定请求标头中提供的 userId 是否为有效的 userId?
  • 不,如果他存在与否,我将验证 DB 中的用户 ID。如果用户 ID 存在,那么他将被重定向到主页,否则将重定向到无效用户页面。如果请求标头中不存在用户 ID,则我们将重定向到登录页面

标签: java spring spring-mvc authentication spring-security


【解决方案1】:

这是一个非常标准的 Spring Security 用例。在遇到任何安全拦截器之前,您需要在安全上下文中提供一个 Authentication 对象。

通常,您会使用某种过滤器从请求中提取 SSO 参数,根据 SSO 服务对这些参数进行身份验证,然后创建一个身份验证对象并将其放入安全上下文中。过滤器的类型和过滤器的配置取决于您使用的 SSO 技术。

通常还会有一个过滤器(通常是 ExceptionTranslationFilter),它将未经身份验证的请求发送到登录页面。

还会有过滤器从登录表单接收参数并将它们存储在安全上下文中。

综合起来,我希望一种可能的工作流程是:

用户使用 SSO 参数登录

  1. 请求中预先填充了凭据
  2. 某些过滤器会提取这些凭据,对其进行验证,然后创建一个身份验证对象,然后将该对象置于安全上下文中。
  3. 安全拦截器在安全上下文中找到 Authentication 对象,验证用户是否可以访问特定功能,然后继续传递请求。

用户无需 SSO 参数即可登录(需要登录页面)

  1. 请求进来时没有凭据
  2. 安全拦截器没有发现 Authentication 对象并抛出异常。
  3. ExceptionTranslationFilter 将异常转换为重定向到登录页面。

用户使用填写的登录表单登录(例如用于 DB 登录)

  1. 请求带有作为实体主体的登录表单
  2. 某些过滤器(例如 UsernamePasswordAuthenticationFilter)从登录表单中提取凭据,并遵从身份验证提供程序(例如您的 DAO 身份验证提供程序)来查询数据库并验证用户。如果经过验证,此过滤器将创建一个身份验证对象并将其放置在安全上下文中。
  3. 安全拦截器在安全上下文中找到 Authentication 对象,验证用户是否可以访问特定功能,然后继续传递请求。

【讨论】:

  • 我试图通过代码来实现这一点,我应该编写一个 Pre Auth Filter 什么样的过滤器,我应该通过 Pre Auth Filter 的异常。如何调用异常翻译过滤器链。你能指导我吗
  • 如果数据在请求头中,那么您不必等待异常,您可以检查数据是否存在,如果存在,则使用它。我会扩展AbstractAuthenticationProcessingFilter 并使用UsernamePasswordAuthenticationFilter 作为示例。
  • 我已经用我迄今为止尝试过的任何方法更新了我的问题,你可以看看它
猜你喜欢
  • 2013-11-20
  • 2013-08-29
  • 1970-01-01
  • 2014-02-18
  • 2014-01-07
  • 2015-12-28
  • 2013-07-16
  • 2016-07-06
  • 2019-07-18
相关资源
最近更新 更多