我正在开发一个spring引导应用程序,它可以根据端点登录API对用户进行身份验证,即:
我们通常直接检查DB中保存的用户名和密码。但是这一次,证书在另一个程序员开发的Login端点API中。
我的Spring引导应用程序,它需要根据该登录api进行用户身份验证“登录表单”。在授予对申请的访问权限之前。换句话说,用户名和密码来自未保存在DB中的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,
}}
发布于 2019-03-13 07:17:41
首先,您需要创建一个客户机来使用rest进行身份验证:
@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);
}
};
}
}您需要在Customer对象中创建登录api响应的DTO,并考虑如何将信息存储到GrantedAuthority列表中。
还有很多其他的选项,你可以使用,但这是容易的我。
编辑:这里只是一个如何为您的身份验证api:实现GrantedAuthority的想法
首先,您需要一个实现接口并存储整个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;
}
}更好的解决方案是创建一个对象并将其存储为一个对象,而不是一个字符串,而仅仅是一个字符串。
然后,您需要在代码中更改访问身份验证api的AuthenticationService:
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();
}
}很抱歉发了这么长的邮件,如果有拼写错误,我很抱歉。正如我所说,这只是我的观点,还有很多其他的解决方案。
https://stackoverflow.com/questions/55135304
复制相似问题