gpt4 book ai didi

spring - 使用 Spring 3 在 REST 中登录/注销

转载 作者:IT老高 更新时间:2023-10-28 13:49:01 26 4
gpt4 key购买 nike

我们正在使用 Spring 3 开发 RESTful Web 服务,我们需要具有登录/注销功能,例如 /webservices/login/<username>/<password>//webservices/logout . session 应存储在上下文中,直到 session 超时或注销以允许使用其他 Web 服务。任何访问没有 session 信息的 web 服务的请求都应该被拒绝。为这种情况寻找最先进的解决方案。

我实际上是在复活这里提出的问题 Spring Security 3 programmatically login ,仍然没有正确回答。请同时在 web.xml 中指定所需的更改。

最佳答案

我建议您完全手动定义 Spring Security 过滤器。这并不难,而且您可以完全控制自己的登录/注销行为。

首先,您需要标准的 web.xml 简介来将过滤器链处理委托(delegate)给 Spring(如果您不在 Servlet API 版本 3 上,请删除异步支持):

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<async-supported>true</async-supported>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>



<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

现在,在安全上下文中,您将为每个路径分别定义过滤器。过滤器可以验证用户、注销用户、检查安全凭证等。

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/login" filters="sif,wsFilter"/>
<sec:filter-chain pattern="/logout" filters="sif,logoutFilter" />
<sec:filter-chain pattern="/rest/**" filters="sif,fsi"/>
</sec:filter-chain-map>
</bean>

上面的 XML 告诉 Spring 通过过滤器链将请求传递到特定的上下文相关 URL。任何过滤器链中的第一件事都是建立安全上下文 - 'sif' bean 负责处理。

<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>

链中的下一个过滤器现在可以将数据添加到安全上下文(读取:登录/注销用户),或者根据所述安全上下文决定是否允许访问。

对于您的登录 URL,您将需要一个过滤器,该过滤器从请求中读取身份验证数据,对其进行验证,然后将其存储在安全上下文中(存储在 session 中):

<bean id="wsFilter" class="my.own.security.AuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="myAuthSuccessHandler"/>
<property name="passwordParameter" value="pass"></property>
<property name="usernameParameter" value="user"></property>
<property name="postOnly" value="false"></property>

您可以使用 Spring 通用 UsernamePasswordAuthenticationFilter 但我使用自己的实现的原因是继续过滤器链处理(默认实现假定用户将在成功的身份验证时被重定向并终止过滤器链),并且能够每次将用户名和密码传递给它时处理身份验证:

public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return ( StringUtils.hasText(obtainUsername(request)) && StringUtils.hasText(obtainPassword(request)) );
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException{
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}

您可以为/login 路径添加任意数量的过滤器实现,例如使用 HTTP 基本身份验证 header 、摘要 header 进行身份验证,甚至从请求正文中提取用户名/密码。 Spring为此提供了一堆过滤器。

我有自己的身份验证成功处理程序,它会覆盖默认重定向策略:

public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

@PostConstruct
public void afterPropertiesSet() {
setRedirectStrategy(new NoRedirectStrategy());
}

protected class NoRedirectStrategy implements RedirectStrategy {

@Override
public void sendRedirect(HttpServletRequest request,
HttpServletResponse response, String url) throws IOException {
// no redirect

}

}

}

如果您可以在成功登录后重定向用户(重定向 URL 可以自定义,请查看文档)

定义将负责检索用户详细信息的身份验证管理器:

<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="myAuthAuthProvider"/>
</sec:authentication-manager>

<bean id="myAuthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="myUserDetailsImpl"/>
</bean>
</property>
</bean>

您必须在此处提供您自己的用户详细信息 bean 实现。

注销过滤器:负责清除安全上下文

<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>

通用认证的东西:

<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>

<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>

访问控制过滤器(应该不言自明):

<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="myAuthenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadataSource">
<sec:filter-invocation-definition-source>
<sec:intercept-url pattern="/rest/**" access="ROLE_REST"/>
</sec:filter-invocation-definition-source>
</property>
</bean>

您还应该能够使用方法上的 @Secured 注释来保护您的 REST 服务。

上面的上下文是从现有的 REST 服务 webapp 中提取的 - 对于任何可能的错别字,我们深表歉意。

也可以通过使用库存的 sec Spring 标记来至少完成这里实现的大部分工作,但我更喜欢自定义方法,因为这给了我最大的控制权。

希望这至少能让你开始。

关于spring - 使用 Spring 3 在 REST 中登录/注销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14733418/

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