首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用restful登录api验证我的spring引导应用程序

使用restful登录api验证我的spring引导应用程序
EN

Stack Overflow用户
提问于 2019-03-13 05:56:31
回答 1查看 4.7K关注 0票数 4

我正在开发一个spring引导应用程序,它可以根据端点登录API对用户进行身份验证,即:

我们通常直接检查DB中保存的用户名和密码。但是这一次,证书在另一个程序员开发的Login端点API中。

我的Spring引导应用程序,它需要根据该登录api进行用户身份验证“登录表单”。在授予对申请的访问权限之前。换句话说,用户名和密码来自未保存在DB中的API!这是其他人已经开发的登录api。有什么想法吗?我以前没这么做过!登录API是:

代码语言:javascript
复制
POST: domain/authenticate/user

该机构是:

代码语言:javascript
复制
{    "username" : "user",  
     "password" : "test"
}

答复如下:

代码语言:javascript
复制
{
"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,
}

}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-13 07:17:41

首先,您需要创建一个客户机来使用rest进行身份验证:

代码语言:javascript
复制
@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;
    }

}

然后您必须创建一个组件或服务来使用该客户端:

代码语言:javascript
复制
@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);
}

}

最后,您需要使用自定义身份验证服务执行基本安全配置:

代码语言:javascript
复制
@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的对象:

代码语言:javascript
复制
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

代码语言:javascript
复制
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进行测试,当用户登录时,测试应该是可见的:

代码语言:javascript
复制
@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();
    }

}

很抱歉发了这么长的邮件,如果有拼写错误,我很抱歉。正如我所说,这只是我的观点,还有很多其他的解决方案。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55135304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档