简体   繁体   English

Spring安全性:处理SSO和DB用户

[英]Spring security : handling SSO and DB users

I have two different types of users. 我有两种不同类型的用户。

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

SSO users would have already been authenticated by different system and DB users should be authenticated by our system. SSO用户将已经由其他系统认证,而DB用户应由我们的系统认证。 Can i configure Spring security to handle this scenario where by i can say prompt login page for some users and don't prompt for some. 我可以配置Spring安全性来处理这种情况吗?在这种情况下,我可以说某些用户的提示登录页面,而不提示某些用户。

Lets say for SSO users i can get there users ID in request headers while DB when they access the application there is no user id present in request header .How can i handle this scenario ? 可以说,对于SSO用户,当他们访问应用程序时,我可以在请求标头中获得用户ID,而在DB访问应用程序时,在请求标头中不存在用户ID。如何处理这种情况?

Can i override authenticate method of DaoAuthenticationProvider by extending it and then page on some parameter decide to authenticate user or is there any other means ? 我可以通过扩展它来覆盖DaoAuthenticationProvider的身份验证方法,然后在某个参数上的页面决定对用户进行身份验证吗,或者还有其他方法吗? can i add any information to Authentication class 我可以向身份验证类添加任何信息吗

This is What i have tried to Far 这就是我试图做到的

Security Config java 安全配置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;
     }
}

My Custom AbstractAuthenticationProcessingFilter 我的自定义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;
    }

}

My Controller 我的控制器

@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;

    }

}

The control goes to My Custom filter and then when the exception is thrown but ExceptionTranslationFilter is not getting called 控件转到“我的自定义”过滤器,然后在引发异常但未调用ExceptionTranslationFilter时

Have i configured httpsecurity correctly Have i configured My custom filter correctly Have i configured ExceptionTranslation Filter Am i missing anything 我是否已正确配置httpsecurity我是否已正确配置我的自定义过滤器我是否已配置ExceptionTranslation过滤器我是否缺少任何内容

This is a pretty standard use case for spring security. 这是用于弹簧安全性的相当标准的用例。 You will need to provide an Authentication object into the security context before any security interceptor is encountered. 在遇到任何安全拦截器之前,您需要在安全上下文中提供一个Authentication对象。

Typically you would have some kind of filter which extracted SSO parameters from the request, authenticated those parameters against the SSO service, and then create an Authentication object and put it into the security context. 通常,您将具有某种过滤器,该过滤器从请求中提取SSO参数,针对SSO服务对这些参数进行身份验证,然后创建一个Authentication对象并将其放入安全上下文中。 The type of filter and configuration of the filter will depend on what SSO technology you are using. 过滤器的类型和过滤器的配置将取决于您使用的SSO技术。

There would often also be a filter (usually an ExceptionTranslationFilter) which will send unauthenticated requests to a login page. 通常还会有一个过滤器(通常是ExceptionTranslationFilter),该过滤器会将未经身份验证的请求发送到登录页面。

There would also be filters to receive the parameters from the login form and store them in the security context. 也将有过滤器从登录表单接收参数并将其存储在安全上下文中。

Putting it all together I would expect one possible workflow to be: 放在一起,我希望一种可能的工作流程是:

User logs in with SSO parameters 用户使用SSO参数登录

  1. Request comes in prepopulated with credentials 请求中预先填充了凭据
  2. Some filter extracts those credentials, verifies them, creates an Authentication object, places the object in the security context. 一些过滤器提取那些凭据,对其进行验证,创建Authentication对象,然后将该对象放置在安全上下文中。
  3. The security interceptor finds the Authentication object in the security context, verifies the user is allowed access to the particular function, and passes the request on. 安全拦截器在安全上下文中找到Authentication对象,验证是否允许用户访问特定功能,并将请求继续传递。

User logs in without SSO parameters (needs login page) 用户无需SSO参数即可登录(需要登录页面)

  1. Request comes in with no credentials 请求没有凭据
  2. The security interceptor finds no Authentication object and throws an exception. 安全拦截器未找到任何身份验证对象,并引发异常。
  3. The ExceptionTranslationFilter turns the exception into a redirect to a login page. ExceptionTranslationFilter将异常转换为重定向到登录页面。

User logs in with filled out login form (eg for DB login) 用户使用填写的登录表单登录(例如,用于数据库登录)

  1. Request comes in with a login form as the entity body 请求带有登录表单作为实体主体
  2. Some filter (eg UsernamePasswordAuthenticationFilter) extracts the credentials from the login form and defers to an authentication provider (eg your DAO authentication provider) to query the database and verify the user. 某些过滤器(例如UsernamePasswordAuthenticationFilter)从登录表单中提取凭据,并转交给身份验证提供程序(例如您的DAO身份验证提供程序)以查询数据库并验证用户。 If verified this filter will create an Authentication object and place it in the security context. 如果验证通过,此过滤器将创建一个Authentication对象,并将其放置在安全上下文中。
  3. The security interceptor finds the Authentication object in the security context, verifies the user is allowed access to the particular function, and passes the request on. 安全拦截器在安全上下文中找到Authentication对象,验证是否允许用户访问特定功能,并将请求继续传递。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM