为 Spring MVC 控制器的方法传递密码 - AOP 或 Spring Security?

发布于 2024-10-16 17:03:27 字数 821 浏览 5 评论 0原文

我已经使用 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 security,但它似乎有点重量级。也许可以使用AOP?

我缺少明显的解决方案吗?

非常感谢, - 斯科特

I have been using Spring MVC for a short while now with annotated controllers for JSP pages. I have a class similar to this:

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

   }    
}   

As you can see, every call will have a password param passed in. The password is read from a dialog and passed into every call that is submitted.

I would like to get rid of the password parameter from the method calls to have 'cleaner' code.

I had a quick look at Spring security for this purpose but it seemed a bit heavyweight. Maybe AOP can be used?

Is there an obvious solution I'm missing?

Many thanks,
- Scott

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时常饿 2024-10-23 17:03:27

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

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

b) 仅密码?切勿在没有用户名的情况下使用密码!通过暴力攻击,任何独立密码最终都会被黑客入侵,但用户名/密码组合更难以破解。

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

使用什么:AOP 还是 Spring Security?

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

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

所以我的建议是:

使用 Spring Security

Spring Security< /a> 是一个自定义解决方案,可以完全满足您的需求:保护基于 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>

摘自 最小 配置

As you can see, every call will have a password param passed in. The password is read from a dialog and passed into every call that is submitted.

a) This is an awful practice. It means that anybody with a network sniffer will be able to see your password all over the place. It might be ok to submit the password once (although it would be better to use a secure way to transmit the password), but then the session should contain the authentication token

b) Password only? Never use a password without a username! With a brute force attack, any standalone-password will eventually be hacked, but username / password combinations are much more difficult to crack.

c) Your controller methods should not know or care about passwords. It's not their concern. They have work to do, dealing with passwords /security is a cross-cutting concern and should not be implemented on the controller level. Which leads us to the Question:

What to use: AOP or Spring Security?

AOP is a very powerful way of implementing cross-cutting functionality, but it has some drawbacks:

  • if you use Spring AOP, advising controllers will only work if you either use interface-backed proxies (and defining interfaces for code that's never called via Java is a bit awkward) or use CGLib-based subclasses through proxy-target-class="true" (in XML config). The latter has funny side effects like double execution of constructors. Many use it, but I would advise against it. Which means Spring AOP is not a good choice.
  • if you use static AspectJ compilation however, you are hardwiring your security concerns into the application code. Security settings should be configurable without recompiling classes, so I'd say we have a no-go here as well.

So my suggestion is:

Use Spring Security

Spring Security is a custom solution for doing exactly what you want: securing Spring based sites (using Spring MVC or another web framework). While Spring Security can be a huge monster, in most cases, the configuration needed is minimal:

<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>

(Taken from the section A Minimal <http> Configuration)

迷途知返 2024-10-23 17:03:27

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

为了检查令牌,您可以从 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>

As mentioned in the previous post its better to submit the login data only once per session and store an authententication token inside the user session.

For checking the token you can implement the HandlerInterceptor interface from the springframework.

For example

public class MyHandlerInterceptor extends HandlerInterceptorAdapter {

public boolean preHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler) throws Exception {

    //check authentication
}

}

and the configuration:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文