简短的回答是否定的。用于管理 Spring Oauth 2 端点的类如下:
@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint
我的意思是,两个请求都获得access token 和refresh 一个使用具有不同参数的相同端点。管理这些的方法是:
@RequestMapping(
value = {"/oauth/token"},
method = {RequestMethod.POST}
)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");
} else {
String clientId = this.getClientId(principal);
...
如您所见,Principal 对象是必需的(在本例中由基本身份验证提供)。
即使,如果您将项目的安全性配置为允许该 url 而不检查身份验证,您将在上述方法中实现“输入”,但您将收到一个 InsufficientAuthenticationException,因为没有提供 Authentication 实例。
为什么自定义身份验证不起作用
1. 创建自定义AuthenticationProvider 将不起作用,因为之前调用了方法postAccessToken。所以你会收到一个InsufficientAuthenticationException。
2. 创建一个OncePerRequestFilter 并将其配置为在处理当前请求之前执行:
@Override
protected void configure(HttpSecurity http) throws Exception {
http...
.anyRequest().authenticated()
.and()
.addFilterBefore(myCustomFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(POST, "/accounts/oauth/**");
}
带有“类似”的代码:
@Component
public class CustomAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
...
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("existingUser",
"passwordOfExistingUser",
Collections.emptyList()));
...
filterChain.doFilter(request, response);
}
这种方法的问题是TokenEndpoint 中的主体来自HttpServletRequest 而不是来自 Spring 上下文,正如您可以看到调试 BasicAuthenticationFilter 类。
在您的自定义过滤器中,您可以尝试使用反射在 userPrincipal 属性中设置一个值,但正如您可以验证的那样,request 有几个“内部 request 属性”,这可能是一个“太棘手的选项” ”。
总之,Oauth 标准需要用户/通行证来访问资源,如果您想在几乎所有提供的端点中解决问题,那么该项目可能不是您想要的。
在 Spring Principal 中包含您自己的对象的解决方法
我不建议这样做,但如果您仍想继续使用这种方法,有一种方法可以将您自己的值包含在 TokenEndpoint 类接收的 principal 参数中。
重要的是要考虑到 BasicAuthorizationFilter 仍将被执行,但是您可以自己覆盖 Spring 主体对象。
为此,我们可以重用以前的CustomAuthenticationFilter,但现在您必须包含您需要的过滤器,我的意思是,允许的 url、参数等您将“打开大门”,所以要小心你的允许和不允许。
在这种情况下的不同之处在于,我们将在扩展 WebSecurityConfigurerAdapter 的类中添加配置,而不是添加:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private CustomAuthenticationFilter customAuthenticationFilter;
...
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.checkTokenAccess("isAuthenticated()");
security.addTokenEndpointAuthenticationFilter(customAuthenticationFilter);
}
...