Spring安全:处理SSO和DB用户

时间:2015-12-14 14:38:57

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

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

  1. SSO用户
  2. 数据库用户。
  3. SSO用户已经过不同系统的身份验证,数据库用户应该通过我们的系统进行身份验证。我可以配置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;
    
        }
    
    }
    

    控件进入My Custom过滤器然后抛出异常但是没有调用ExceptionTranslationFilter

    我是否正确配置了httpsecurity 我是否正确配置了自定义过滤器 我配置了ExceptionTranslation Filter 我错过了什么

1 个答案:

答案 0 :(得分:1)

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

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

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

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

总而言之,我希望有一个可能的工作流程:

用户使用SSO参数登录

  1. 请求预先填充凭据
  2. 某些过滤器会提取这些凭据,验证它们,创建Authentication对象,将对象放在安全上下文中。
  3. 安全拦截器在安全上下文中查找Authentication对象,验证用户是否可以访问特定函数,并传递请求。
  4. 用户登录时没有SSO参数(需要登录页面)

    1. 请求没有凭据
    2. 安全拦截器找不到Authentication对象并抛出异常。
    3. ExceptionTranslationFilter将异常转换为重定向到登录页面。
    4. 用户使用填写的登录表单登录(例如,用于DB登录)

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