Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring Security Cookie+;JWT认证_Java_Spring_Authentication_Spring Security - Fatal编程技术网

Java Spring Security Cookie+;JWT认证

Java Spring Security Cookie+;JWT认证,java,spring,authentication,spring-security,Java,Spring,Authentication,Spring Security,我必须说,我对整个模型感到非常困惑,我需要帮助将所有浮动部分粘合在一起 我不是在做SpringREST,只是简单的WebMVC控制器 我的使命: 我想要一个用户名+通过身份验证的表单登录。我想对第三方服务进行身份验证。成功后,我希望返回一个cookie,但不使用默认的cookie令牌机制。我希望cookie中有一个JWT令牌。通过利用cookie机制,每个请求都将与JWT一起发送 因此,要分解它,我需要处理以下模块: 在执行用户+pas登录时针对第三方服务进行身份验证 n 成功身份验证后,用自定

我必须说,我对整个模型感到非常困惑,我需要帮助将所有浮动部分粘合在一起

我不是在做SpringREST,只是简单的WebMVC控制器

我的使命: 我想要一个用户名+通过身份验证的表单登录。我想对第三方服务进行身份验证。成功后,我希望返回一个cookie,但不使用默认的cookie令牌机制。我希望cookie中有一个JWT令牌。通过利用cookie机制,每个请求都将与JWT一起发送

因此,要分解它,我需要处理以下模块:

  • 在执行用户+pas登录时针对第三方服务进行身份验证 n
  • 成功身份验证后,用自定义实现替换cookie会话令牌

  • 根据每个请求从cookie解析JWT(使用过滤器)

  • 从JWT中提取用户详细信息/数据,以便控制器访问

  • 什么让人困惑?(请纠正我的错误)

    第三方身份验证

    要针对第三方进行身份验证,我需要通过扩展AuthenticationProvider来拥有一个自定义的提供程序

    public class JWTTokenAuthenticationProvider implements AuthenticationProvider { 
    
          @Override
          public Authentication authenticate( Authentication authentication ) throws AuthenticationException {
    
              // auth against 3rd party
    
              // return Authentication
              return new UsernamePasswordAuthenticationToken( name, password, new ArrayList<>() );
    
          }
    
          @Override
          public boolean supports(Class<?> authentication) {
              return authentication.equals( UsernamePasswordAuthenticationToken.class );
          }
    
    }
    
    问题:

    • 什么时候调用AbstractAuthenticationProcessingFilter#successfulAuthentication?它是在用户登录时调用的,还是在JWT令牌成功验证时调用的
    • 此筛选器与我以前发布的自定义提供程序之间是否存在任何关系?管理器将根据令牌实例调用自定义提供者,该令牌实例与提供者通过支持方法支持的内容相匹配
    似乎除了cookie会话替换之外,我已经拥有了所有需要的部分,但我无法将它们放在一个连贯的模型中,我需要一个足够了解机制的人,这样我就可以将所有这些都粘合到一个模块中

    更新1

    好的,我想我已经到了起点

    此筛选器将自身注册为POST->“/login”,然后创建UsernamePasswordAuthenticationToken的实例,并将控件传递给下一个筛选器

    问题是cookie会话设置在哪里

    更新2

    dos的这一部分给出了我所缺少的顶级流程,无论是谁,请看这里

    本节介绍AuthenticationProvider

    更新3-工作案例,这是最好的方法吗??

    所以在翻阅了Spring安全文档及其来源之后,我得到了初始模型。现在,这样做,我意识到有不止一种方法。关于为什么选择这种方式与Denys在下面提出的方式相比,有什么建议吗


    下面的工作示例…

    最简单的方法是将Spring会话添加到项目中,并扩展它,为会话创建/销毁事件提供方便的挂钩,并具有从HttpServletRequest提取会话的方法

    要使这项工作按原帖子所述的方式进行,这就是需要发生的事情

    自定义过滤器

    public class CookieAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    
            public CookieAuthenticationFilter( RequestMatcher requestMatcher ) {
    
                super( requestMatcher );
                setAuthenticationManager( super.getAuthenticationManager() );
    
            }
    
            @Override
            public Authentication attemptAuthentication( HttpServletRequest request, HttpServletResponse response )
                throws AuthenticationException, IOException, ServletException {
    
                String token = "";
    
                // get token from a Cookie
                Cookie[] cookies = request.getCookies();
    
                if( cookies == null || cookies.length < 1 ) {
                    throw new AuthenticationServiceException( "Invalid Token" );
                }
    
                Cookie sessionCookie = null;
                for( Cookie cookie : cookies ) {
                    if( ( "someSessionId" ).equals( cookie.getName() ) ) {
                    sessionCookie = cookie;
                    break;
                    }
                }
    
                // TODO: move the cookie validation into a private method
                if( sessionCookie == null || StringUtils.isEmpty( sessionCookie.getValue() ) ) {
                    throw new AuthenticationServiceException( "Invalid Token" );
                }
    
                JWTAuthenticationToken jwtAuthentication = new JWTAuthenticationToken( sessionCookie.getValue(), null, null );
    
                return jwtAuthentication;
    
            }
    
    
            @Override
            public void doFilter(ServletRequest req, ServletResponse res,
                     FilterChain chain) throws IOException, ServletException {
                super.doFilter(req, res, chain);
            }
    
    }
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired @Required
        ApiAuthenticationProvider apiAuthProvider;
    
        @Autowired @Required
        AuthenticationSuccessHandler authSuccessHandler;
    
        @Autowired @Required
        SimpleUrlAuthenticationFailureHandler authFailureHandler;
    
        @Override
        protected void configure( AuthenticationManagerBuilder auth ) throws Exception {
        auth.authenticationProvider( apiAuthProvider );
        }
    
        @Override
        protected void configure( HttpSecurity httpSecurity ) throws Exception {
    
                httpSecurity
    
                // don't create session
                .sessionManagement()
                    .sessionCreationPolicy( SessionCreationPolicy.STATELESS )
                    .and()
    
                .authorizeRequests()
                    .antMatchers( "/", "/login", "/register" ).permitAll()
                    .antMatchers( "/js/**", "/css/**", "/img/**" ).permitAll()
                    .anyRequest().authenticated()
                    .and()
    
                // login
                .formLogin()
                    .failureHandler( authFailureHandler )
                    //.failureUrl( "/login" )
                    .loginPage("/login")
                    .successHandler( authSuccessHandler )
                            .and()
    
                // JWT cookie filter
                .addFilterAfter( getCookieAuthenticationFilter(
                        new AndRequestMatcher( new AntPathRequestMatcher( "/account" ) )
                ) , UsernamePasswordAuthenticationFilter.class );
        }
    
    
        @Bean
        SimpleUrlAuthenticationFailureHandler getAuthFailureHandler() {
    
                SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler( "/login" );
                handler.setDefaultFailureUrl( "/login" );
                //handler.setUseForward( true );
    
                return handler;
    
        }
    
        CookieAuthenticationFilter getCookieAuthenticationFilter( RequestMatcher requestMatcher ) {
    
                CookieAuthenticationFilter filter = new CookieAuthenticationFilter( requestMatcher );
                filter.setAuthenticationFailureHandler( authFailureHandler );
                return filter;
        }
    }
    
    }

    将这一切联系在一起

    public class CookieAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    
            public CookieAuthenticationFilter( RequestMatcher requestMatcher ) {
    
                super( requestMatcher );
                setAuthenticationManager( super.getAuthenticationManager() );
    
            }
    
            @Override
            public Authentication attemptAuthentication( HttpServletRequest request, HttpServletResponse response )
                throws AuthenticationException, IOException, ServletException {
    
                String token = "";
    
                // get token from a Cookie
                Cookie[] cookies = request.getCookies();
    
                if( cookies == null || cookies.length < 1 ) {
                    throw new AuthenticationServiceException( "Invalid Token" );
                }
    
                Cookie sessionCookie = null;
                for( Cookie cookie : cookies ) {
                    if( ( "someSessionId" ).equals( cookie.getName() ) ) {
                    sessionCookie = cookie;
                    break;
                    }
                }
    
                // TODO: move the cookie validation into a private method
                if( sessionCookie == null || StringUtils.isEmpty( sessionCookie.getValue() ) ) {
                    throw new AuthenticationServiceException( "Invalid Token" );
                }
    
                JWTAuthenticationToken jwtAuthentication = new JWTAuthenticationToken( sessionCookie.getValue(), null, null );
    
                return jwtAuthentication;
    
            }
    
    
            @Override
            public void doFilter(ServletRequest req, ServletResponse res,
                     FilterChain chain) throws IOException, ServletException {
                super.doFilter(req, res, chain);
            }
    
    }
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired @Required
        ApiAuthenticationProvider apiAuthProvider;
    
        @Autowired @Required
        AuthenticationSuccessHandler authSuccessHandler;
    
        @Autowired @Required
        SimpleUrlAuthenticationFailureHandler authFailureHandler;
    
        @Override
        protected void configure( AuthenticationManagerBuilder auth ) throws Exception {
        auth.authenticationProvider( apiAuthProvider );
        }
    
        @Override
        protected void configure( HttpSecurity httpSecurity ) throws Exception {
    
                httpSecurity
    
                // don't create session
                .sessionManagement()
                    .sessionCreationPolicy( SessionCreationPolicy.STATELESS )
                    .and()
    
                .authorizeRequests()
                    .antMatchers( "/", "/login", "/register" ).permitAll()
                    .antMatchers( "/js/**", "/css/**", "/img/**" ).permitAll()
                    .anyRequest().authenticated()
                    .and()
    
                // login
                .formLogin()
                    .failureHandler( authFailureHandler )
                    //.failureUrl( "/login" )
                    .loginPage("/login")
                    .successHandler( authSuccessHandler )
                            .and()
    
                // JWT cookie filter
                .addFilterAfter( getCookieAuthenticationFilter(
                        new AndRequestMatcher( new AntPathRequestMatcher( "/account" ) )
                ) , UsernamePasswordAuthenticationFilter.class );
        }
    
    
        @Bean
        SimpleUrlAuthenticationFailureHandler getAuthFailureHandler() {
    
                SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler( "/login" );
                handler.setDefaultFailureUrl( "/login" );
                //handler.setUseForward( true );
    
                return handler;
    
        }
    
        CookieAuthenticationFilter getCookieAuthenticationFilter( RequestMatcher requestMatcher ) {
    
                CookieAuthenticationFilter filter = new CookieAuthenticationFilter( requestMatcher );
                filter.setAuthenticationFailureHandler( authFailureHandler );
                return filter;
        }
    }
    

    谢谢你的小费,丹尼斯!这就是我感到困惑的地方,有很多方法可以实现同样的目标,我可以用三种不同的方法来实现这一点,包括你提出的方法。有人能解释一下为什么我会选择我提出的问题和你提出的问题吗?这个例子看起来并不完整。它在“JWTAuthenticationToken没有AuthenticationProvider”上抛出错误。我正在尝试做与您相同的流,但找不到任何有用的资源。您有github链接吗?希望我能多次更新此链接。非常有用,谢谢@AssafMoldavsky.CookieAuthenticationFilter.attemptAuthentication被调用了两次,知道为什么会发生这种情况吗。我按原样实现了上述解决方案。@AssafMoldavsky-您在github中有这样的示例吗?你能提供完整的代码吗?
    @Component
    public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    
        @Override
        public void onAuthenticationSuccess(
                    HttpServletRequest request, 
                    HttpServletResponse response, 
                    Authentication authentication) throws IOException, ServletException {
    
            if( !(authentication instanceof JWTAuthenticationToken) ) {
                return;
            }
    
            JWTAuthenticationToken jwtAuthenticaton =    (JWTAuthenticationToken) authentication;
    
            // Add a session cookie
            Cookie sessionCookie = new Cookie( "someSessionId", jwtAuthenticaton.getToken() );
            response.addCookie( sessionCookie );
    
            //clearAuthenticationAttributes(request);
    
            // call the original impl
            super.onAuthenticationSuccess( request, response, authentication );
    }
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired @Required
        ApiAuthenticationProvider apiAuthProvider;
    
        @Autowired @Required
        AuthenticationSuccessHandler authSuccessHandler;
    
        @Autowired @Required
        SimpleUrlAuthenticationFailureHandler authFailureHandler;
    
        @Override
        protected void configure( AuthenticationManagerBuilder auth ) throws Exception {
        auth.authenticationProvider( apiAuthProvider );
        }
    
        @Override
        protected void configure( HttpSecurity httpSecurity ) throws Exception {
    
                httpSecurity
    
                // don't create session
                .sessionManagement()
                    .sessionCreationPolicy( SessionCreationPolicy.STATELESS )
                    .and()
    
                .authorizeRequests()
                    .antMatchers( "/", "/login", "/register" ).permitAll()
                    .antMatchers( "/js/**", "/css/**", "/img/**" ).permitAll()
                    .anyRequest().authenticated()
                    .and()
    
                // login
                .formLogin()
                    .failureHandler( authFailureHandler )
                    //.failureUrl( "/login" )
                    .loginPage("/login")
                    .successHandler( authSuccessHandler )
                            .and()
    
                // JWT cookie filter
                .addFilterAfter( getCookieAuthenticationFilter(
                        new AndRequestMatcher( new AntPathRequestMatcher( "/account" ) )
                ) , UsernamePasswordAuthenticationFilter.class );
        }
    
    
        @Bean
        SimpleUrlAuthenticationFailureHandler getAuthFailureHandler() {
    
                SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler( "/login" );
                handler.setDefaultFailureUrl( "/login" );
                //handler.setUseForward( true );
    
                return handler;
    
        }
    
        CookieAuthenticationFilter getCookieAuthenticationFilter( RequestMatcher requestMatcher ) {
    
                CookieAuthenticationFilter filter = new CookieAuthenticationFilter( requestMatcher );
                filter.setAuthenticationFailureHandler( authFailureHandler );
                return filter;
        }
    }