Spring 安全和 JSON 身份验证

2024-01-09

我在 spring/spring-mvc 中有一个完全使用 JSON 通信的应用程序。 现在我需要通过 JSON 使用 spring security 3(使用 LdapAuthenticationProvider)对我的应用程序进行身份验证。

默认的 spring security 提交表单需要这样的 POST:

POST /myapp/j_spring_security_check HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
Host: 127.0.0.1:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

j_username=myUsername&j_password=myPass

但我想传递一个像这样的 JSON 对象:

{"j_username":"myUsername","j_password":"myPass"}

我读了很多帖子,比如this https://stackoverflow.com/questions/3444864/ajax-login-with-spring-webmvc-and-spring-security, 这个其他 http://gal-levinsky.blogspot.co.il/2011/08/spring-security-3-ajax-login.html or this one http://raibledesigns.com/rd/entry/implementing_ajax_authentication_using_jquery如果运气不好,在所有 ajax 情况下都会像上面那样完成 POST。

有任何想法吗?


根据凯文的建议,
阅读这篇文章后:1 https://stackoverflow.com/questions/14829825/custom-spring-3-0-security-filters-multiple-entrypoints-authenticationprovider, 2 https://stackoverflow.com/questions/7384842/usernamepasswordauthenticationfilter-problem、文档3 http://docs.spring.io/spring-security/site/docs/3.0.x/reference/ns-config.html,并感谢this http://beansgocrazy.blogspot.it/2011/07/custom-authentication-with-spring.html博客文章,
我编写了自己的 FORM_LOGIN_FILTER 来在身份验证之前直接管理 JSON。
我将我的代码粘贴到社区。

目标是同时授予经典浏览器表单 POST 身份验证和基于 JSON 的身份验证。另外,在 JSON 身份验证中,我想避免重定向到 loginSuccesful.htm

在上下文中:

<security:http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">      
    <security:intercept-url pattern="/logs/**" access="denyAll" />
    <!-- ... All other intercept URL -->

    <security:custom-filter ref="CustomUsernamePasswordAuthenticationFilter" position="FORM_LOGIN_FILTER "/>
    <security:logout
            invalidate-session="true"
            logout-success-url="/LogoutSuccessful.htm"
            delete-cookies="true"
    />
    <security:session-management>
        <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
    </security:session-management>
    <security:access-denied-handler error-page="/accessDenied.htm" />
</security:http>

<bean id="CustomUsernamePasswordAuthenticationFilter" class="path.to.CustomUsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationSuccessHandler" ref="customSuccessHandler"/>
    <property name="authenticationFailureHandler" ref="failureHandler"/>
    <property name="filterProcessesUrl" value="/j_spring_security_check"/>
    <property name="usernameParameter" value="j_username"/>
    <property name="passwordParameter" value="j_password"/>
</bean>

<bean id="customSuccessHandler" class="path.to.CustomAuthenticationSuccessHandler">
    <property name="defaultTargetUrl" value="/login.htm" />
    <property name="targetUrlParameter" value="/LoginSuccessful.htm" />
</bean>

<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/login.htm" />
</bean>

<bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

自定义用户名密码验证过滤器类:

public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
    private String jsonUsername;
    private String jsonPassword;

    @Override
    protected String obtainPassword(HttpServletRequest request) {
        String password = null; 

        if ("application/json".equals(request.getHeader("Content-Type"))) {
            password = this.jsonPassword;
        }else{
            password = super.obtainPassword(request);
        }

        return password;
    }

    @Override
    protected String obtainUsername(HttpServletRequest request){
        String username = null;

        if ("application/json".equals(request.getHeader("Content-Type"))) {
            username = this.jsonUsername;
        }else{
            username = super.obtainUsername(request);
        }

        return username;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
        if ("application/json".equals(request.getHeader("Content-Type"))) {
            try {
                /*
                 * HttpServletRequest can be read only once
                 */
                StringBuffer sb = new StringBuffer();
                String line = null;

                BufferedReader reader = request.getReader();
                while ((line = reader.readLine()) != null){
                    sb.append(line);
                }

                //json transformation
                ObjectMapper mapper = new ObjectMapper();
                LoginRequest loginRequest = mapper.readValue(sb.toString(), LoginRequest.class);

                this.jsonUsername = loginRequest.getUsername();
                this.jsonPassword = loginRequest.getPassword();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return super.attemptAuthentication(request, response);
    }
}

自定义 AuthenticationSuccessHandler 类:

public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    public void onAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication auth
    )throws IOException, ServletException {

        if ("application/json".equals(request.getHeader("Content-Type"))) {
            /*
             * USED if you want to AVOID redirect to LoginSuccessful.htm in JSON authentication
             */         
            response.getWriter().print("{\"responseCode\":\"SUCCESS\"}");
            response.getWriter().flush();
        } else {
            super.onAuthenticationSuccess(request, response, auth);
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring 安全和 JSON 身份验证 的相关文章

随机推荐

  • jquery:检测滚动位置

    我希望在滚动时看到页脚时收到警报 window on mousewheel function if window scrollTop window height gt footer position top alert footer vis
  • T-SQL 是否有用于连接字符串的聚合函数? [复制]

    这个问题在这里已经有答案了 可能的重复 SQL Server 2000中的内爆类型函数 https stackoverflow com questions 534724 implode type function in sql server
  • 将 Whatsapp Markdown 转换为 HTML 标签

    我需要将 Whatsapp markdown 转换为 HTML 标签 Eg Bold to b Bold b Italic to i Italic i 我想使用正则表达式来捕获字符串中的单词 这是链接 包含测试用例 以及我的最佳尝试 htt
  • 为什么loadedmetadata 不能持续触发

    有谁知道为什么loadedmetadata在chrome上不能持续触发 如果您在检查控制台时打开此页面并保持刷新 您将看到只有三分之一会触发 http output jsbin com petefipepa http output jsbi
  • Base64 反序列化期间的空引用异常 (C#)

    我使用以下方法来序列化和反序列化 NET 对象 public static string SerializeToBase64 object data var stream new MemoryStream var formatter new
  • 在lua中使用cURL

    我正在尝试在一个小 lua 脚本中使用curl 库 我知道有一个 k 选项可以禁用curl默认执行的认证验证 但我一直无法找到如何通过代码来做到这一点 到目前为止 这是我所拥有的 local cURL require cURL header
  • 如何设置内置输入(OSX Core Audio / Audio Unit)的输入电平(增益)?

    我有一个 OSX 应用程序 它使用音频单元记录音频数据 音频单元的输入可以设置为任何可用的输入源 包括内置输入 问题是 我从内置输入获得的音频经常被削波 而在 Audacity 甚至 Quicktime 等程序中 我可以调低输入电平 但不会
  • PYTHONPATH 不适用于 GNU/Linux 上的 sudo(适用于 root)

    编辑 适用于 root sudo 是问题所在 参见下文 我有一个包含我自己的库的目录 例如我的 Python 库位于 home name lib py 我已将此目录添加到Python 的路径对于所有用户 包括 root 添加以下行 etc
  • 半音阶乐器调音器的稳健算法? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 谁知道半音阶乐器调音器最强大的算法 我正在尝试编写一个乐器调音器 我尝试过以下两种算法 FFT 创建韦尔
  • 哪个 OpenSSL 版本支持 SHA256?

    我编写了一个 PHP 库 它使用openssl verify and openssl sign 使用 SHA256 我认为 SHA256 支持对于 PHP 和 OpenSSL 来说是一种新功能 但我不知道哪个版本开始支持 SHA256 这会
  • 将逗号分隔的字符串转换为单独的行

    我有一个这样的 SQL 表 SomeID OtherID Data abcdef cdef123 18 20 22 abcdef 4554a24 17 19 987654 12324a2 13 19 20 是否有一个查询可以执行类似的查询S
  • C++ 函数模板编译错误“‘containerType’不是模板”

    我正在尝试编写一个函数来 字符串化 参数以用于记录目的 例如 我想写这样的东西 vector
  • DirectX 或 OpenGL [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如果您正在用 C 编写下一个 3D 图形密集型应用程序 例如 3D 建模和动画软件 那么哪一个是更好的选择 如果我们认为 C 是独立于平台的 那
  • 如何配置此 Spring-Boot 应用程序以使用 IAM 角色而不是密钥和机密?

    我有一个与 S3 和 SQS 通信的 Spring Boot 应用程序 它使用 AWS 密钥和机密工作得很好 但我发现我有一个限制 因为我不能使用这些凭证 而必须使用 IAM 实例角色进行身份验证 我没有运气让这个微小的改变发挥作用 我创建
  • 消息队列和共享内存的区别?

    我读了很多关于消息队列和共享内存之间差异的文章 但仍不清楚哪一种有利于获得良好的性能 就像共享内存应该比队列更好 但在同步它的情况下也存在性能问题 共享内存和消息队列都可以用来在进程之间交换信息 区别在于how他们被使用了 共享内存正如您所
  • 如何在 Vim 中的 html 标签之间粘贴内容?

    紧迫p将内容粘贴到当前行下方 dit删除 html 标签内的内容 如何在 html 标签内粘贴内容 Nor here p I want to paste something here p Not here 我通常只是这样做vitp它直观地选
  • VS 2010可以自动检查/更新头文件吗?

    这几乎就是我的问题 VS 2010 可以自动检查和更新 C 代码中的头文件吗 VS 2010可以自动从头文件生成cpp文件 从而节省您从头文件复制函数定义的时间吗 我的意思是 它是否可以认为某些方法没有实现 并从头文件中找到的声明生成一个空
  • 量角器可以慢速运行吗?

    有没有办法缓慢运行使用量角器编写的 Angular E2E 测试 以便我可以观察正在发生的情况 以下是我的解决方案 所以基本上我为当前控制流创建了一个装饰器execute函数 现在在每个排队操作之前额外排队 100 毫秒的延迟 这需要在调用
  • Spring MVC @ResponseBody 返回一个列表

    我们想创建一个 WebService 它返回特定对象的列表 我们想通过 apache http 客户端库从另一个 java 程序调用这个 Web 服务 此时 如果我们从 Firefox 中调用 Web 服务 则会出现 406 错误页面 我们
  • Spring 安全和 JSON 身份验证

    我在 spring spring mvc 中有一个完全使用 JSON 通信的应用程序 现在我需要通过 JSON 使用 spring security 3 使用 LdapAuthenticationProvider 对我的应用程序进行身份验证