【问题标题】:Passing a password for methods for Spring MVC Controller - AOP or Spring Security?为 Spring MVC 控制器的方法传递密码 - AOP 还是 Spring Security?
【发布时间】:2011-06-23 09:50:52
【问题描述】:

我使用 Spring MVC 已经有一段时间了,现在将带注释的控制器用于 JSP 页面。我有一个类似的课程:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
public class AdminController {

   @RequestMapping(value = "/doStuff1.htm", method = RequestMethod.POST)
   public void doStuff1(@RequestParam("password")String password) {

        // do some stuff

   }

   @RequestMapping(value = "/doStuff2.htm", method = RequestMethod.POST)    
   public void doStuff2(
       @RequestParam("password")String password,
       @RequestParam("foo")String foo{

        // do some stuff

   }    
}   

如您所见,每个调用都会传入一个密码参数。密码是从对话框中读取的,并传递给每个提交的调用。

我想从方法调用中去掉密码参数以获得“更清晰”的代码。

为此,我快速浏览了 Spring 安全性,但它似乎有点重量级。或许可以使用AOP?

我是否缺少明显的解决方案?

非常感谢, - 斯科特

【问题讨论】:

    标签: java spring spring-mvc spring-security aop


    【解决方案1】:

    如您所见,每个调用都会传入一个密码参数。密码从对话框中读取并传递给每个提交的调用。

    a) 这是一种糟糕的做法。这意味着任何拥有网络嗅探器的人都可以在任何地方看到您的密码。提交一次密码可能没问题(虽然最好使用安全的方式来传输密码),但是会话应该包含身份验证令牌

    b) 只有密码?永远不要使用没有用户名的密码!通过暴力攻击,任何独立密码最终都会被破解,但用户名/密码组合更难破解。

    c) 你的控制器方法不应该知道或关心密码。这不是他们关心的问题。他们有工作要做,处理密码/安全是一个跨领域的问题,不应该在控制器级别实现。这就引出了我们的问题:

    使用什么:AOP 还是 Spring Security?

    AOP 是一种非常强大的实现横切功能的方式,但它也有一些缺点:

    • 如果您使用Spring AOP,建议控制器仅在您使用接口支持的代理(并且为从未通过 Java 调用的代码定义接口有点尴尬)或通过proxy-target-class="true" 使用基于 CGLib 的子类(在 XML 配置中)。后者具有有趣的副作用,例如构造函数的双重执行。许多人使用它,但我建议不要使用它。这意味着 Spring AOP 不是一个好的选择。
    • 但是,如果您使用静态AspectJ 编译,则您将安全问题硬连接到应用程序代码中。安全设置应该可以在不重新编译类的情况下进行配置,所以我想说我们也不能这样做。

    所以我的建议是:

    使用 Spring Security

    ​​>

    Spring Security 是一个自定义解决方案,可以完全满足您的需求:保护基于 Spring 的站点(使用 Spring MVC 或其他 Web 框架)。虽然 Spring Security 可能是一个巨大的怪物,但在大多数情况下,所需的配置是最少的:

    <http auto-config='true'>
        <!-- restrict all URLs to role ROLE_USER -->
        <intercept-url pattern="/**" access="ROLE_USER" />
    </http>
    <authentication-manager>
        <authentication-provider>
          <user-service>
            <!-- define two users, jimi and bob -->
            <user name="jimi" password="jimispassword"
                  authorities="ROLE_USER, ROLE_ADMIN" />
            <user name="bob" password="bobspassword"
                  authorities="ROLE_USER" />
          </user-service>
        </authentication-provider>
    </authentication-manager>
    

    (取自A Minimal &lt;http&gt; Configuration部分)

    【讨论】:

      【解决方案2】:

      如上一篇文章所述,最好在每个会话中只提交一次登录数据,并在用户会话中存储一个身份验证令牌。

      为了检查令牌,您可以从 springframework 实现HandlerInterceptor 接口。

      例如

      public class MyHandlerInterceptor extends HandlerInterceptorAdapter {
      
      public boolean preHandle(HttpServletRequest request,
              HttpServletResponse response, Object handler) throws Exception {
      
          //check authentication
      }
      

      }

      和配置:

      <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
      <property name="interceptors">
          <list>
              <bean id="myInterceptor" class="...MyInterceptor"/>
          </list>
      </property>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-17
        • 2017-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多