美文网首页
结合springboot和keycloak做登陆验证

结合springboot和keycloak做登陆验证

作者: LOC_Thomas | 来源:发表于2017-02-14 15:52 被阅读0次

    前言

    登陆是一个项目的基础,几乎任何项目都需要包括登陆模块,网上大部分登陆都是使用的shrio,个人感觉这种东西很老,而且不好用,偶然之前发现了一个叫keycloak的sso开源项目, 感觉挺不错的,这篇文章主要讲解如何使用springboot和keycloak进行结合。

    版本

    1. springboot: 1.4.3.RELEASE 版本
    2. keycloak: 2.5.1.Final 版本
    3. vue: 2.1.0 版本

    项目搭建

    1. 首先搭建keycloak的服务 (略)
    2. 编写前端代码(用vue2写的简单的一个spa,略)
    3. 编写springboot的服务(略)
    4. 加入核心依赖
            <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-tomcat8-adapter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-spring-security-adapter</artifactId>
            </dependency>
    
    1. 在springboot的配置文件中加入
    keycloak:
           configurationFile: "classpath:keycloak.json"
    
    1. 在resources的目录下加入 keycloak.json 配置文件
    {
      "realm": "family",
      "bearer-only": true,
      "auth-server-url": "http://localhost:8080/auth",
      "ssl-required": "external",
      "resource": "family-app",
      "enable-cors": true
    }
    
    1. 配置springmvc的跨域filter
    @Configuration
    public class CorsFilterConfig implements Filter {
    
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {}
    
      @Override
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
          FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) servletResponse;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        res.setHeader("Access-Control-Max-Age", "1728000");
        res.setHeader("Access-Control-Allow-Headers",
            "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
        filterChain.doFilter(servletRequest, res);
      }
    
      @Override
      public void destroy() {}
    }
    
    1. 配置keycloak和spring security结合的配置文件
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
    public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(keycloakAuthenticationProvider());
      }
    
      @Bean
      @Override
      protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new NullAuthenticatedSessionStrategy();
      }
    
      @Bean
      public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
          KeycloakAuthenticationProcessingFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
      }
    
      @Bean
      public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
          KeycloakPreAuthActionsFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
      }
    
      @Override
      protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .sessionAuthenticationStrategy(sessionAuthenticationStrategy()).and()
            .addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
            .addFilterBefore(keycloakAuthenticationProcessingFilter(), X509AuthenticationFilter.class)
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint()).and()
            .authorizeRequests()
            .requestMatchers(CorsUtils::isCorsRequest).permitAll()
    //        .antMatchers("/family/*").hasAnyAuthority("user").antMatchers("/admin/*").hasRole("ADMIN")
            .antMatchers("/**").authenticated()
            .anyRequest().permitAll();
      }
    }
    
    1. 对应的接口上增加可以执行的用户角色
    @RequestMapping(value = "/all", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
      @ResponseBody
      @PreAuthorize("hasAnyAuthority('user')")
      public List<Family> queryAllFamilyInfo() {
        return familyInfoService.queryAllFamilyInfo();
      }
    

    遇到的坑

    1. 对应keycloak的用户权限需要使用 hasAnyAuthority而不是 hasAnyRole,并且需要在KeycloakSecurityConfig类中加入@EnableGlobalMethodSecurity(prePostEnabled = true) 注解
    2. keycloak-spring-security-adapterspring-boot-adpater 两个依赖不能同时使用
    3. cors的跨域的配置,需要CorsFilterConfig的filter类配合KeycloakSecurityConfig类中的 requestMatchers(CorsUtils::isCorsRequest).permitAll()一起使用

    完整的项目地址(包括了简单的前端和后端代码,不会写前端,前端代码比较垃圾。。 需要完善 ):

    https://github.com/dragontree101/springboot-keycloak-demo

    相关文章

      网友评论

          本文标题:结合springboot和keycloak做登陆验证

          本文链接:https://www.haomeiwen.com/subject/tdwxwttx.html