1

レスト サービス認証を基本認証からフォーム ベース認証に変換しようとしていますが、次のようなクエリ パラメータとして URL で認証の詳細を送信すると、以下のコードは正常に動作します (カスタム認証フィルタをコメントアウトしたことに注意してください)。http://localhost:8080/login?username=dfdf&&password=sdsdd

ただし、資格情報をクエリ パラメーターとして送信することに熱心ではなく、代わりに json として送信したいので、カスタム認証フィルターを作成しました。カスタム認証フィルターを追加すると、Spring セッションが機能しなくなります。x-auth-token応答ヘッダーにフィールドが見つかりません。春のセッションとカスタム認証を一緒に有効にする方法、または資格情報のjson入力を処理するより簡単な方法かもしれません。

@Configuration
@EnableWebSecurity
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private ObjectMapper objectMapper;

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

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        builder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/register", "/index.html").permitAll().and().authorizeRequests()
                .anyRequest().authenticated().and().requestCache().requestCache(new NullRequestCache()).and()
                .formLogin().failureHandler(getRESTAuthenticationFailureHandler())
                .successHandler(getRESTAuthenticationSuccessHandler()).usernameParameter("username")
                .passwordParameter("password").and().exceptionHandling()
                .authenticationEntryPoint(getRESTAuthenticationEntryPoint()).and()
                //.addFilter(getAuthenticationFilter())
                .csrf().disable();
    }

    @Bean
    public HttpSessionStrategy httpSessionStrategy() {
        return new HeaderHttpSessionStrategy();
    }

    @Bean
    public RESTAuthenticationEntryPoint getRESTAuthenticationEntryPoint() {
        return new RESTAuthenticationEntryPoint();
    }

    @Bean
    public RESTAuthenticationSuccessHandler getRESTAuthenticationSuccessHandler() {
        return new RESTAuthenticationSuccessHandler();
    }

    @Bean
    public RESTAuthenticationFailureHandler getRESTAuthenticationFailureHandler() {
        return new RESTAuthenticationFailureHandler();
    }

    @Bean
    public AuthenticationFilter getAuthenticationFilter() {
        AuthenticationFilter filter = new AuthenticationFilter();
        try {
            filter.setAuthenticationManager(this.authenticationManager());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return filter;
    }

    public class RESTAuthenticationEntryPoint implements AuthenticationEntryPoint {

        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
                AuthenticationException authException) throws IOException, ServletException {

            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }

    public class RESTAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws IOException, ServletException {
            clearAuthenticationAttributes(request);

        }
    }

    public class RESTAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                AuthenticationException exception) throws IOException, ServletException {

            super.onAuthenticationFailure(request, response, exception);
        }
    }

    public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

        private final Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);

        private boolean postOnly = true;

        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                throws AuthenticationException {
            if (postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            }

            String username = null;
            String password = null;
            UserDetails userDetails = null;
            if ("application/json".equals(request.getHeader("Content-Type"))) {
                userDetails = getJson(request);
                if (userDetails != null) {
                    username = userDetails.getUsername();
                }
            } else {
                username = obtainUsername(request);
            }

            if ("application/json".equals(request.getHeader("Content-Type"))) {

                if (userDetails != null) {
                    password = userDetails.getPassword();
                }

            } else {
                password = obtainPassword(request);
            }

            if (username == null) {
                username = "";
            }

            if (password == null) {
                password = "";
            }

            username = username.trim();

            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
                    password);

            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);

            return this.getAuthenticationManager().authenticate(authRequest);
        }

        private UserDetails getJson(HttpServletRequest request) {

            try {
                final List<String> data = IOUtils.readLines(request.getReader());
                final String jsonData = data.stream().collect(Collectors.joining());
                LOG.info(jsonData);
                UserDetails userDetails = objectMapper.readValue(jsonData, UserDetails.class);
                return userDetails;
            } catch (IOException e) {
                LOG.error("Failed to read data {}", e.getMessage(), e);
                return null;
            }

        }

    }

}
4

1 に答える 1