我已经苦苦挣扎了好几天了.我是Spring Boot的新手,并且喜欢不使用XML配置的想法.
我创建了一个RESTfull应用程序(使用JSON).我正在按照本教程正确配置身份验证.
我认为我设法使用Java配置重现几乎所有的配置,除了一件事 - AuthenticationEntryPoint
本教程使用http像这样的标记中的属性,并按以下方式定义formLogin:
<http entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/api/admin/**" access="ROLE_ADMIN"/>
<form-login
authentication-success-handler-ref="mySuccessHandler"
authentication-failure-handler-ref="myFailureHandler"
/>
<logout />
</http>
Run Code Online (Sandbox Code Playgroud)
Spring Security手册中的AuthenticationEntryPoint解释说:
可以使用<http>元素上的entry-point-ref属性设置AuthenticationEntryPoint.
没有提到有关如何使用Java配置执行此操作的任何内容.
那么如何restAuthenticationEntryPoint在没有XML 的情况下"注册"我自己的,以防止在使用formLogin时重定向到登录表单?
下面我将提到我尝试过的内容.
谢谢你们.
在我的尝试中,发现你可以使用basicAuth定义它,如下所示:
@Configuration
@Order(1)
public static class RestWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
if (restAuthenticationEntryPoint == null) {
restAuthenticationEntryPoint = new RestAuthenticationEntryPoint();
}
http
.authorizeRequests()
.antMatchers("/**").hasAnyRole(Sec.ADMIN,Sec.SUPER_USER)
...
.and()
.httpBasic()
.authenticationEntryPoint(restAuthenticationEntryPoint)
Run Code Online (Sandbox Code Playgroud)
但我正在使用这样的表单登录(没有 …
使用自定义Spring Security过滤器,如果HTTP标头不包含特定的键值对,我想返回HTTP 401错误代码.
例:
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
final String val = request.getHeader(FOO_TOKEN)
if(val == null || !val.equals("FOO")) {
// token is not valid, return an HTTP 401 error code
...
}
else {
// token is good, let it proceed
chain.doFilter(req, res);
}
Run Code Online (Sandbox Code Playgroud)
据我了解,我可以做以下事情:
(1)((HttpServletResponse) res).setStatus(401)并跳过剩余的过滤链
要么
(2)抛出异常,最终导致Spring Security向客户端抛出401错误.
如果#1是更好的选择,如何在调用setStatus(401)响应后跳过过滤器链?
或者,如果#2是正确的方法,我应该抛出哪个例外?
如何在纯资源服务器上获取我的自定义ResponseEntityExceptionHandler或OAuth2ExceptionRenderer处理Spring安全性引发的异常?
我们实施了一个
@ControllerAdvice
@RestController
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
Run Code Online (Sandbox Code Playgroud)
因此,只要资源服务器上出现错误,我们就希望它能够回答
{
"message": "...",
"type": "...",
"status": 400
}
Run Code Online (Sandbox Code Playgroud)
资源服务器使用application.properties设置:
security.oauth2.resource.userInfoUri: http://localhost:9999/auth/user
Run Code Online (Sandbox Code Playgroud)
对我们的auth服务器进行身份验证和授权请求.
但是,任何弹簧安全性错误都将始终绕过我们的异常处理程
@ExceptionHandler(InvalidTokenException.class)
public ResponseEntity<Map<String, Object>> handleInvalidTokenException(InvalidTokenException e) {
return createErrorResponseAndLog(e, 401);
}
Run Code Online (Sandbox Code Playgroud)
并生产
{
"timestamp": "2016-12-14T10:40:34.122Z",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/api/templates/585004226f793042a094d3a9/schema"
}
Run Code Online (Sandbox Code Playgroud)
要么
{
"error": "invalid_token",
"error_description": "5d7e4ab5-4a88-4571-b4a4-042bce0a076b"
}
Run Code Online (Sandbox Code Playgroud)
那么如何配置资源服务器的安全性异常处理呢?我找到的只是如何通过实现自定义来自定义Auth服务器的示例OAuth2ExceptionRenderer.但我无法找到将其连接到资源服务器的安全链的位置.
我们唯一的配置/设置是这样的:
@SpringBootApplication
@Configuration
@ComponentScan(basePackages = {"our.packages"})
@EnableAutoConfiguration
@EnableResourceServer
Run Code Online (Sandbox Code Playgroud) spring security oauth 的错误格式符合 OAuth 规范,看起来像这样。
{
"error":"insufficient_scope",
"error_description":"Insufficient scope for this resource",
"scope":"do.something"
}
Run Code Online (Sandbox Code Playgroud)
特别是在资源服务器上,我发现为身份验证问题获取不同的错误格式有点奇怪。所以我想改变这个异常的呈现方式。
该文件说:
授权服务器中的错误处理使用标准的 Spring MVC 特性,即 @ExceptionHandler 方法
所以我尝试了这样的事情来自定义错误的格式:
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyErrorHandler {
@ExceptionHandler(value = {InsufficientScopeException.class})
ResponseEntity<MyErrorRepresentation> handle(RuntimeException ex, HttpServletRequest request) {
return errorResponse(HttpStatus.FORBIDDEN,
MyErrorRepresentation.builder()
.errorId("insufficient.scope")
.build(),
request);
}
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用。
查看代码,所有的错误渲染似乎都是在DefaultWebResponseExceptionTranslator#handleOAuth2Exception. 但是实现自定义WebResponseExceptionTranslator不允许更改格式。
任何提示?
我正在使用 Spring 在更大的应用程序中公开 API。当访问authentiated()配置后面的端点时,我的应用程序由于以下代码而抛出一个丑陋的Tomcat HTML错误:
@Component
public class EntryPointUnauthorizedHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied");
}
}
Run Code Online (Sandbox Code Playgroud)
但是,由于这是一个 API,我只想返回 JSON,就像 API 的其余部分一样。对于正常的异常处理,我设置了以下内容@ControllerAdvice:
@ControllerAdvice
public class DefaultExceptionHandler extends ResponseEntityExceptionHandler {
/**
* Default internal BadCredentialsException handler. Respond with 401 Unauthorized
*/
@ExceptionHandler(value = BadCredentialsException.class)
public ResponseEntity<Object> handleBadCredentialsException(BadCredentialsException e, WebRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return handleExceptionInternal(e, null, headers, HttpStatus.UNAUTHORIZED, request);
}
/**
* …Run Code Online (Sandbox Code Playgroud) 我是 Spring Security 的新手。
我有一段代码,用于检查请求中是否传递了授权标头,如果缺少,则抛出异常。
public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private static final String BEARER = "Bearer";
public TokenAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
super(requiresAuthenticationRequestMatcher);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String username = request.getParameter("username");
String authorization = request.getHeader("AUTHORIZATION");
if (!request.getRequestURI().equals(UniversalConstants.LOGIN_PATH)) {
if (authorization == null || authorization.length() == 0 || !authorization.startsWith(BEARER)) {
throw new InvalidCredentialsException("Missing authentication token"); //<-----------------
}
}
String password = request.getParameter("password");
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
Run Code Online (Sandbox Code Playgroud)
我的目标是在全球范围内处理所有异常,因此我使用@ControllerAdvice。
注意:我知道 @ControllerAdvice 不适用于从 …
怎么处理UsernameNotFoundException?
在 spring security 中,当找不到用户名时,UserDetailsService实现会抛出一个UsernameNotFoundException. 例如像这样:
@Override
@Transactional
public UserDetails loadUserByUsername(java.lang.String username) throws UsernameNotFoundException {
logger.info("Load user by username: {}", username);
User user = userRepository.findUserByUsername(username).orElseThrow(
() -> new UsernameNotFoundException("User Not Found with -> username or email: " + username));
return UserPrinciple.build(user);
}
Run Code Online (Sandbox Code Playgroud)
我想构建一个自定义的“用户未找到 REST 响应”。我应该如何捕获/处理这个异常?我在 WebSecurityConfigurerAdapter 实现处理程序中实现了一个处理程序方法:
private static void handleException(HttpServletRequest req, HttpServletResponse rsp, AuthenticationException e)
throws IOException {
PrintWriter writer = rsp.getWriter();
writer.println(new ObjectMapper().writeValueAsString(new AuthResponse("", null, null, null, null,
"Authentication failed.", false)));
rsp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); …Run Code Online (Sandbox Code Playgroud)