spring-mvc - Spring Security 表单后认证
问题描述
我有一个可以通过表单发布请求访问的页面(移动应用程序的 webview 页面)。我的应用程序没有登录表单,但我需要保护它。移动应用程序将使用身份验证参数(例如(电子邮件/密码))调用此 web 视图页面。我需要使用给定的身份验证参数调用第三方 api 并确定它是否经过身份验证。我应该为我的场景使用哪种方法?
解决方案
如果可以在Authorization
标头中传递身份验证参数,则可以在应用程序中启用 http 基本身份验证:
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
否则,您可以实现自己的安全过滤器,以从您的特定身份验证参数创建UsernamePasswordAuthenticationToken
(或任何其他实现的类Authentication
)实例并传递给AuthenticationManager
; 但在另一个类的情况下,您需要通过覆盖该public boolean supports(Class<?> authentication)
方法使下面的身份验证提供程序支持它。
然后实现一个自定义AuthenticationProvider
,将身份验证委托给第三方 API,例如:
public class RestAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private static final String AUTH_URL = "http://third-party-service/authentication/basic";
private RestTemplate restTemplate;
public RestAuthenticationProvider() {
this.restTemplate = new RestTemplate();
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (authentication.getCredentials() == null) {
this.logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
if (!authentication.getCredentials().toString().equals(userDetails.getPassword())) {
this.logger.debug("Authentication failed: invalid credentials");
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) {
String password = authentication.getCredentials().toString();
try {
ResponseEntity<String> authenticationResponse = authenticate(username, password);
if (authenticationResponse.getStatusCode().value() == 401) {
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
return createUser(authenticationResponse.getBody());
} catch (BadCredentialsException ex) {
throw ex;
} catch (Exception ex) {
throw new InternalAuthenticationServiceException(ex.getMessage(), ex);
}
}
private ResponseEntity<String> authenticate(String username, String password) {
HttpEntity entity = new HttpEntity(createHeaders(username, password));
return restTemplate.exchange(AUTH_URL, HttpMethod.GET, entity, String.class);
}
private HttpHeaders createHeaders(String username, String password) {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
String authorization = username + ":" + password;
String basic = Base64.getEncoder().encodeToString(authorization.getBytes());
headers.set("Authorization", "Basic " + basic);
return headers;
}
private UserDetails createUser(String json) {
return null; // TODO: Implement
}
}
最后,让 Spring Security 使用您的提供程序:
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(new RestAuthenticationProvider())
.eraseCredentials(false);
}
推荐阅读
- javascript - 以表格格式放置一组图像
- java - 我有一个 kotlin Gif 解码器代码,但我希望这段代码用 java 编写
- angular-cli - Angular Service Worker 忽略相对路径
- docker-compose - 配置 jmx-prometheus-exporter docker 容器以读取 jmx 本地应用程序的指标
- json - 如何修复 ReactNative 中发送的“Json Parse Error: Unexpected EOF”错误?
- java - 计算一个字符在字符串中以连续方式出现的次数
- express-gateway - 如何管理消费者的凭据
- android - React Native 上的浮动按钮(FAB)在渲染 Modal、iOS Actionsheet、选择器组件时不会停留在顶部
- javascript - tabBarVisible: false 不适用于 stackNavigation 子项
- node.js - Google Cloud AppEngine - NPM 依赖项 - 身份验证凭据无效