gpt4 book ai didi

java - 通过 Spring 进行 RESTful 身份验证

转载 作者:bug小助手 更新时间:2023-10-28 10:40:11 25 4
gpt4 key购买 nike

问题:
我们有一个基于 Spring MVC 的 RESTful API,其中包含敏感信息。 API 应该是安全的,但是在每个请求中都发送用户的凭据(用户/密码组合)是不可取的。根据 REST 准则(和内部业务要求),服务器必须保持无状态。该 API 将由另一台服务器以 mashup 样式的方式使用。

要求:

  • 客户端使用凭据向 .../authenticate(不 protected URL)发出请求;服务器返回一个安全 token ,其中包含足够的信息供服务器验证 future 的请求并保持无状态。这可能包含与 Spring Security 的 Remember-Me Token 相同的信息。 .

  • 客户端向各种( protected )URL 发出后续请求,将先前获得的 token 附加为查询参数(或者,不太理想的是,附加一个 HTTP 请求 header )。

  • 不能期望客户端存储 cookie。

  • 既然我们已经使用了 Spring,那么解决方案应该使用 Spring Security。

我们一直在努力解决这个问题,所以希望有人已经解决了这个问题。

鉴于上述情况,您将如何解决这一特殊需求?

最佳答案

我们设法使这项工作完全按照 OP 中的描述进行,希望其他人可以使用该解决方案。这是我们所做的:

像这样设置安全上下文:

<security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="CustomAuthenticationEntryPoint">
<security:custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER" />
<security:intercept-url pattern="/authenticate" access="permitAll"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>

<bean id="CustomAuthenticationEntryPoint"
class="com.demo.api.support.spring.CustomAuthenticationEntryPoint" />

<bean id="authenticationTokenProcessingFilter"
class="com.demo.api.support.spring.AuthenticationTokenProcessingFilter" >
<constructor-arg ref="authenticationManager" />
</bean>

如您所见,我们创建了一个自定义 AuthenticationEntryPoint,如果请求未在过滤器链中通过我们的身份验证,它基本上只会返回 401 Unauthorized AuthenticationTokenProcessingFilter.

CustomAuthenticationEntryPoint:

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." );
}
}

AuthenticationTokenProcessingFilter:

public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

@Autowired UserService userService;
@Autowired TokenUtils tokenUtils;
AuthenticationManager authManager;

public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
this.authManager = authManager;
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
@SuppressWarnings("unchecked")
Map<String, String[]> parms = request.getParameterMap();

if(parms.containsKey("token")) {
String token = parms.get("token")[0]; // grab the first "token" parameter

// validate the token
if (tokenUtils.validate(token)) {
// determine the user based on the (already validated) token
UserDetails userDetails = tokenUtils.getUserFromToken(token);
// build an Authentication object with the user's info
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request));
// set the authentication into the SecurityContext
SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(authentication));
}
}
// continue thru the filter chain
chain.doFilter(request, response);
}
}

很明显,TokenUtils 包含一些私密(并且非常特定于案例)代码,不能轻易共享。这是它的界面:

public interface TokenUtils {
String getToken(UserDetails userDetails);
String getToken(UserDetails userDetails, Long expiration);
boolean validate(String token);
UserDetails getUserFromToken(String token);
}

这应该会让你有个好的开始。

关于java - 通过 Spring 进行 RESTful 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10826293/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com