Аутентификация моего весеннего загрузочного приложения с использованием успокоительного API входа - PullRequest
1 голос
/ 13 марта 2019

Привет, ребята, во-первых, не унижайте мой Вопрос, потому что я искал везде, но не смог найти четкую реализацию! Но, тем не менее, некоторым людям все равно, и они продолжают унижать мой вопрос ...

Я разрабатываю приложение с загрузочной пружиной, которое аутентифицирует пользователя по API входа в конечную точку, т.е. Обычно мы проверяем имя пользователя и пароль, сохраненные в БД напрямую. Но на этот раз учетные данные В API конечной точки входа в систему, который был разработан другим программистом.

Загрузочное приложение My Spring, для которого требуется пользовательская «форма входа» для аутентификации в соответствии с API входа в систему. Прежде чем предоставить доступ к приложению. Другими словами, имя пользователя и пароль происходят из API, не сохраненного в БД! Какой это логин API уже разработан другими. Любая идея? Я не делал этого раньше! API входа в систему:

POST: domain/authenticate/user

Тело это:

{    "username" : "user",  
     "password" : "test"
}

Ответ:

{
"customer": {
    "id": 62948,
    "email": "test@test.com.au",
    "givenName": "A",
    "familyName": "OB",
    "user": {
        "id": 63158,
        "version": 1,
        "email": "adamo@test.com.au",
        "password": "113b984921197350abfedb0a30f6e215beeda6c718e36559f48eae946664b405c77bc6bab222fe8d3191f82925921438b6566dda76613aa6cd4416e5d9ae51c8",
        "givenName": "A",
        "familyName": "OB",
     },
    "vehicles": [
        {
            "id": 79369,
            "version": 0,
            "country": "Australia"
            },
            "newState": null,
        }
    ],
    "fundingSources": [
        {
            "@class": "au.com.test.test",
            "id": 54795,
            "version": 0,
        }
    ],

    "citySuburb": null,
}

}

1 Ответ

2 голосов
/ 13 марта 2019

Сначала вам нужно создать клиент, который будет использовать ваши остальные API для аутентификации:

@Service
public class AuthService {

    @Bean
    public RestTemplate authRestTemplate() {
        return new RestTemplateBuilder().rootUri("http://domain/authenticate").build();
    }

    public Customer authenticate(MultiValueMap<String, String> request) {
        return authRestTemplate().postForObject("/user", request, Customer.class);
    }

    public MultiValueMap<String, String> createRequest(String username, String password) {
        MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
        request.add("username", username);
        request.add("password", password);
        return request;
    }

}

Затем вам нужно создать компонент или сервис для использования этого клиента:

@Service
public class AuthenticationService implements AuthenticationProvider {

private AuthService authService;

@Autowired
public void setAuthService(AuthService authService) {
    this.authService = authService;
}

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    String username = authentication.getName();
    String password = authentication.getCredentials().toString();

    Customer customer = authService.authenticate(authService.createRequest(username, password));
    if (customer != null) {
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
//here you need to store your Customer object to use it anywhere while the user is logged in
// take a look on the edit
        grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities);
    }
    throw new AuthenticationServiceException("Invalid credentials.");

}

@Override
public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
}

}

Наконец, вам нужно выполнить базовую настройку безопасности с помощью вашей пользовательской службы аутентификации:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration implements WebMvcConfigurer {

    private AuthenticationService authenticationService;

    @Autowired
    public void setAuthenticationService(AuthenticationService authenticationService) {
        this.authenticationService = authenticationService;
    }

    @Bean
    public WebSecurityConfigurerAdapter webSecurityConfig() {
        return new WebSecurityConfigurerAdapter() {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                        .csrf()
                        .disable()
                        .authorizeRequests()
                        .antMatchers("/webjars/**").permitAll()
                        .anyRequest().authenticated()
                        .and()
                        .formLogin()
                        .loginPage("/login")
                        .permitAll()
                        .and()
                        .logout()
                        .permitAll();
            }

            @Override
            protected void configure(AuthenticationManagerBuilder builder) throws Exception {
                builder.authenticationProvider(authenticationService);
            }

        };

        }
}

Вам необходимо создать DTO вашего ответа API входа в систему в Customer объекте и подумать о том, как сохранить информацию всписок GrantedAuthority

Есть много других опций, которые вы можете использовать, но для меня это просто.

Редактировать: Вот только идея, как реализоватьGrantedAuthority для вашей аутентификации API:

Сначала вам нужен объект, который реализует интерфейс и хранит весь JSON:

public class CustomerGrantedAuthority implements org.springframework.security.core.GrantedAuthority {

    private String customerJson;

    public CustomerGrantedAuthority(String customerJson){
        this.customerJson = customerJson;
    }

    @Override
    public String getAuthority() {
        return customerJson;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CustomerGrantedAuthority that = (CustomerGrantedAuthority) o;
        return java.util.Objects.equals(customerJson, that.customerJson);
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(customerJson);
    }

    @Override
    public String toString() {
        return this.customerJson;
    }

}

Лучшее решение состоит в создании объекта исохраните его как объект не как строку, а просто для примера, это строка.

Затем вам нужно изменить AuthenticationService в вашем коде, где вы получаете доступ к API аутентификации:

String customer = new RestTemplate().postForObject("http://domain/authenticate/user", createRequest(username, password), String.class);
    if (customer != null) {
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    grantedAuthorities.add(new CustomerGrantedAuthority(new ObjectMapper().writeValueAsString(customer)));
        grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities);
    }
    throw new AuthenticationServiceException("Invalid credentials.");

public MultiValueMap<String, String> createRequest(String username, String password) {
            MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
            request.add("username", username);
            request.add("password", password);
            return request;
        }

Это зависит от того, где и как вы хотите получить доступ к своей информации о пользователе в вашем приложении, но просто для того, чтобы увидеть, работает ли она, вы можете сделать тест с простым RestController, который должен быть виден при входе пользователя в систему:

@RestController
public class TestController {

    @GetMapping(value = "/auth")
    public ResponseEntity getAuth() {
        Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
        CustomerGrantedAuthority customer = (CustomerGrantedAuthority) authorities.stream().findFirst().orElse(null);
        return customer != null ? ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(customer.getAuthority()) : ResponseEntity.notFound().build();
    }

}

Извините за длинный пост, и я прошу прощения, если есть орфографические ошибки.Как я уже сказал, это только мое мнение, и есть много других решений.

...