当前位置: 首页 > 面试题库 >

带有其余Web服务的Spring MVC + Spring Security登录

宗穆冉
2023-03-14
问题内容

我有一个SpringMVC Web应用程序,需要通过发送用户名和密码来使用Spring Security对RESTful
Web服务进行身份验证。登录用户时,需要将cookie设置到用户的浏览器,并且在后续调用中,使用cookie使用另一个RESTful
Web服务验证用户会话。

我到处都在寻找,但是我找不到一个很好的例子来说明如何做到这一点,我的所有尝试都是徒劳的。

这是我的想法:

我可以声明两个身份验证提供者,第一个检查cookie,如果由于某种原因它失败,则转到第二个,检查用户名和密码(如果该请求中没有用户名和密码,也会失败) 。

这两个服务每次都返回用户的权限,并且spring安全性是“无状态的”。

另一方面,我一直在问自己这种方法是否正确,因为很难找到一个例子或遇到相同问题的其他人。这种方法是错误的吗?

之所以要执行此操作而不是仅执行JDBC身份验证,是因为我的整个Web应用程序都是无状态的,并且始终通过包裹“请愿队列”的RESTful
Web服务来访问数据库,因此我想在用户身份验证方面尊重这一点,并且验证也。

到目前为止,我尝试了什么?我可以粘贴很长的springSecurity-context.xml,但是现在我只列出它们:

  1. 将自定义authenticationFilter与authenticationSuccessHandler一起使用。显然不起作用,因为此时用户已经登录。
  2. 实现入口点引用过滤器。
  3. 在BASIC_AUTH_FILTER位置执行自定义过滤器
  4. 制作一个自定义的身份验证提供程序(苦苦挣扎,没有运气!)。当我得到一些答案时,我正在重试此操作。
  5. 当我决定写一个问题时,我开始使用CAS。也许将来我可以考虑在我的Web应用程序中使用CAS服务器,但是就目前而言,这感觉像是一个过大的杀伤力。

提前致谢!

顺便说一句,我正在使用Spring Security 3.1.4和Spring MVC 3.2.3

编辑:我有能力感谢@coder ANSWER

以下是我所做的事情,我将尝试记录所有这些并将其发布在此处或不久后发布在博客中:

<http use-expressions="true" create-session="stateless" entry-point-ref="loginUrlAuthenticationEntryPoint"
        authentication-manager-ref="customAuthenticationManager">
    <custom-filter ref="restAuthenticationFilter" position="FORM_LOGIN_FILTER" />
    <custom-filter ref="restPreAuthFilter" position="PRE_AUTH_FILTER" />
    <intercept-url pattern="/signin/**" access="permitAll" />
    <intercept-url pattern="/img/**" access="permitAll" />
    <intercept-url pattern="/css/**" access="permitAll" />
    <intercept-url pattern="/js/**" access="permitAll" />
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

</http>

<authentication-manager id="authManager" alias="authManager">
    <authentication-provider ref="preauthAuthProvider" />
</authentication-manager>

<beans:bean id="restPreAuthFilter" class="com.company.CustomPreAuthenticatedFilter">
    <beans:property name="cookieName" value="SessionCookie" />
    <beans:property name="checkForPrincipalChanges" value="true" />
    <beans:property name="authenticationManager" ref="authManager" />
</beans:bean>

<beans:bean id="preauthAuthProvider"
    class="com.company.CustomPreAuthProvider">
    <beans:property name="preAuthenticatedUserDetailsService">
        <beans:bean id="userDetailsServiceWrapper"
            class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <beans:property name="userDetailsService" ref="userDetailsService" />
        </beans:bean>
    </beans:property>
</beans:bean>

<beans:bean id="userDetailsService" class="com.company.CustomUserDetailsService" />

<beans:bean id="loginUrlAuthenticationEntryPoint"
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:constructor-arg value="/signin" />
</beans:bean>

<beans:bean id="customAuthenticationManager"
    class="com.company.CustomAuthenticationManager" />

<beans:bean id="restAuthenticationFilter"
    class="com.company.CustomFormLoginFilter">
    <beans:property name="filterProcessesUrl" value="/signin/authenticate" />
    <beans:property name="authenticationManager" ref="customAuthenticationManager" />
    <beans:property name="authenticationFailureHandler">
        <beans:bean
            class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
            <beans:property name="defaultFailureUrl" value="/login?login_error=t" />
        </beans:bean>
    </beans:property>
</beans:bean>

自定义实现是这样的:

// Here, the idea is to write authenticate method and return a new UsernamePasswordAuthenticationToken
public class CustomAuthenticationManager implements AuthenticationManager { ... }

// Write attemptAuthentication method and return UsernamePasswordAuthenticationToken 
public class CustomFormLoginFilter extends UsernamePasswordAuthenticationFilter { ... }

// Write getPreAuthenticatedPrincipal and getPreAuthenticatedCredentials methods and return cookieName and cookieValue respectively
public class CustomPreAuthenticatedFilter extends AbstractPreAuthenticatedProcessingFilter { ... }

// Write authenticate method and return Authentication auth = new UsernamePasswordAuthenticationToken(name, token, grantedAuths); (or null if can't be pre-authenticated)
public class CustomPreAuthProvider extends PreAuthenticatedAuthenticationProvider{ ... }

// Write loadUserByUsername method and return a new UserDetails user = new User("hectorg87", "123456", Collections.singletonList(new GrantedAuthorityImpl("ROLE_USER")));
public class CustomUserDetailsService implements UserDetailsService { ... }

问题答案:
  1. 您可以通过扩展AbstractPreAuthenticatedProcessingFilter来定义自定义的预身份验证过滤器。
  2. 在您的getPreAuthenticatedPrincipal()方法的实现中,您可以检查cookie是否存在,以及是否存在cookie的返回cookie名称和凭据中的cookie值。
  3. 使用PreAuthenticatedAuthenticationProvider并提供自定义的preAuthenticatedUserDetailsS​​ervice来检查cookie是否为vali,如果cookie的合法性也可以获取授予的权限,则其他方法会抛出AuthenticationException,例如BadCredentialsException
  4. 要使用用户名/密码对用户进行身份验证,请添加表单登录过滤器,基本过滤器或具有自定义身份验证提供程序(或自定义userdetailsS​​ervice)的自定义过滤器,以验证用户/密码

如果存在cookie,pre
auth过滤器将在springContext中设置经过身份验证的用户,并且不会调用您的用户名。/password过滤器,如果cookie为misisng /
invalid,则身份验证入口点将使用用户名/密码触发身份验证

希望能帮助到你



 类似资料:
  • 错误日志: 浏览器出错 org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常为java.lang.IllegalArgumentException:无效的处理程序方法返回值:false org.springframework.web.servlet.frameworkServlet.processRequest(framew

  • 问题内容: 我正在编写一个AJAX函数,该函数从JSON Python Web服务请求数据。我的AJAX请求如下所示: 现在,我的python网络服务具有一个处理对“ / blah”的请求的函数,该函数具有以下return语句: 我的AJAX函数无法从Python Web服务成功检索响应,但是在Firebug中没有出现任何错误。我的网络服务或JavaScript做错了什么? 问题答案: 当您使用J

  • 我必须使用axis2和Maven在eclipse中创建一个web服务,但我有很多问题。这是波姆。xml: Eclipse给了我这个错误:Description资源路径位置类型插件执行未包含在lifecycle configuration:org中。阿帕奇。axis2:axis2-java2wsdl-maven-plugin:1.5.4:java2wsdl(执行:默认,阶段:流程类)pom。xml/

  • 我有一组RESTful web服务,通常部署在Glassfish服务器中。问题是,我工作的地方只与Apache一起工作,所以我不得不切换,现在是问题出现的地方。我已经成功地部署了两个RESTful资源,它们工作得很好(它们所做的只是从数据库中检索信息,并在POJO的ArrayList中返回该信息)。 我手动设置了库,甚至下载了该死的JerseyClientBuilder,但这些都不管用。提前谢谢你

  • 我已经在restful web服务中实现了Spring Security性。 OAuth访问令牌请求 http://localhost:8084/Weekenter/oauth/token?grant_type=password 作为响应,我将获得访问令牌和刷新令牌。 现在我可以通过以下查询字符串参数使用给定的访问令牌请求API服务method.and完美运行。 请求格式 在上面的快照中,我有格式

  • 我正在学习springsecurity(基于java的配置),我无法使注销正常工作。当我点击注销时,我看到URL更改为http://localhost:8080/logout并获取“HTTP 404-/logout”。登录功能工作正常(即使使用自定义登录表单),但问题是注销,我怀疑重定向的url“localhost:8080/logout”应该类似于“localhost:8808/springte

  • 我检查了其他几个类似的问题,但没有找到解决方案。 因此,我有一个配置了web服务的spring boot项目: ServiceImpl,例如: 服务运行良好。 我的POM实现如下所示: 主要类别: 到目前为止,一切都很好-WS是可达的,但如果我添加到POM: 应用程序启动,我可以在日志中看到: endpoint处理程序映射:映射”{[/info EndpointHandlerMapping:映射的