Spring security- Send credentials as json instead of regular form in rest service

后端 未结 2 509
轻奢々
轻奢々 2020-12-17 03:44

I am writing rest service with json. For backend I use Spring Security. I have form witch sends with ajax rest object as follow:

相关标签:
2条回答
  • 2020-12-17 04:28

    You can extend and override WebSecurityConfigurerAdapter

    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .csrf().disable()
                .addFilter(new UserNamePasswordAuthFilter(authenticationManager(), userRepo))
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(daoAuthenticationProvider());
        }
        
        @Bean
        public DaoAuthenticationProvider daoAuthenticationProvider() {
            DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
            provider.setUserDetailsService(userDetailsService); // custom user service
            provider.setPasswordEncoder(passwordEncoder); // custom password encoder
            return provider;
        }
    

    Then you can define a filter for authentication and optionally you can override successful login behavior.

    public class UserNamePasswordAuthFilter extends UsernamePasswordAuthenticationFilter {
    
        private final AuthenticationManager authManager;
        private final AecUserRepo userRepo;
        
        public UserNamePasswordAuthFilter(AuthenticationManager authManager, AecUserRepo userRepo) {
            super();
            this.authManager = authManager;
            this.userRepo = userRepo;
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request,
                HttpServletResponse response) throws AuthenticationException {
    
            try {
                // Get username & password from request (JSON) any way you like
                UsernamePassword authRequest = new ObjectMapper()
                        .readValue(request.getInputStream(), UsernamePassword.class);
                
                Authentication auth = new UsernamePasswordAuthenticationToken(authRequest.getUsername(), 
                        authRequest.getPassword());
                
                return authManager.authenticate(auth);
            } catch (Exception exp) {
                throw new RuntimeException(exp);
            }
        }
        
        @Override
        protected void successfulAuthentication(HttpServletRequest request,
                HttpServletResponse response, FilterChain chain, Authentication authResult)
                throws IOException, ServletException {
    
            if (logger.isDebugEnabled()) {
                logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
                        + authResult);
            }
    
            // custom code
            
            SecurityContextHolder.getContext().setAuthentication(authResult);       
        }
    }
    
    0 讨论(0)
  • 2020-12-17 04:42

    Well, it must not work until you write the getUserNamePasswordAuthenticationToken body.

    Actually, you must read the request body of the HttpServletRequest, parse it through Jackson or any other mapping way and create with it the UsernamePasswordAuthenticationToken.

    Using Jackson (choose the right version depending on your Spring version), I would create a simple bean like this:

    @JsonIgnoreProperties(ignoreUnkown=true)
        public LoginRequest{
         private String email;
         private String password;
         // getters & setters
        }
    

    The use it to map it the request body:

    private UsernamePasswordAuthenticationToken getUserNamePasswordAuthenticationToken(HttpServletRequest request)  throws IOException{
        StringBuffer sb = new StringBuffer();
        BufferedReader bufferedReader = null;
        String content = "";
        LoginRequest sr = null;
    
        try {
            bufferedReader =  request.getReader()
            char[] charBuffer = new char[128];
            int bytesRead;
            while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
                sb.append(charBuffer, 0, bytesRead);
            }
            content = sb.toString();
            ObjectMapper objectMapper = new ObjectMapper();
            try{
                sr = objectMapper.readValue(content, LoginRequest.class);
            }catch(Throwable t){
                throw new IOException(t.getMessage(), t);
            }
        } catch (IOException ex) {
    
            throw ex;
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ex) {
                    throw ex;
                }
            }
        }
        return new UsernamePasswordAuthenticationToken(sr.getEmail(), sr.getPassword());
    

    }

    P.D. Yo must use Post, you will never be able to post a request-body using GET

    0 讨论(0)
提交回复
热议问题