技术开发 频道

使用Spring Security保护Web应用的安全

  清单 4. 获取当前认证用户的用户名

                
public static String getAuthenticatedUsername() {
    
String username = null;
    
Object principal = SecurityContextHolder.getContext()
        .getAuthentication().getPrincipal();
    
if (principal instanceof UserDetails) {
        username
= ((UserDetails) principal).getUsername();
    }
else {
        username
= principal.toString();
    }
    return username;
}

  默认情况下,SecurityContextHolder使用 ThreadLocal来保存 SecurityContext对象。因此,SecurityContext对象对于当前线程上所有方法都是可见的。这种实现对于 Web 应用来说是合适的。不过在有些情况下,如桌面应用,这种实现方式就不适用了。Spring Security 允许开发人员对此进行定制。开发人员只需要实现接口 org.springframework.security.core.context.SecurityContextHolderStrategy并通过 SecurityContextHolder的 setStrategyName(String)方法让 Spring Security 使用此实现即可。另外一种设置方式是使用系统属性。除此之外,Spring Security 默认提供了另外两种实现方式:MODE_GLOBAL表示当前应用共享唯一的 SecurityContextHolder;MODE_INHERITABLETHREADLOCAL表示子线程继承父线程的 SecurityContextHolder。代码清单 5给出了使用全局唯一的 SecurityContextHolder的示例。

  清单 5. 使用全局唯一的 SecurityContextHolder

public void useGlobalSecurityContextHolder() {
    SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
}

  在介绍完 Spring Security 中的 SecurityContext和 Authentication之后,下面介绍如何保护服务层的方法。

  服务层方法保护

  之前章节中介绍的是在 URL 这个粒度上的安全保护。这种粒度的保护在很多情况下是不够的。比如相同的 URL 对应的页面上,不同角色的用户所能看到的内容和执行的操作是有可能不同的。在第一个示例应用中,系统中记录了每个员工的工资收入。所有员工都可以查看自己的工资,但是只有员工的直接经理才可以修改员工的工资。这就涉及到对应用中服务层的方法进行相应的权限控制,从而避免安全漏洞。

  保护服务层方法涉及到对应用中的方法调用进行拦截。通过 Spring 框架提供的良好面向方面编程(AOP)的支持,可以很容易的对方法调用进行拦截。Spring Security 利用了 AOP 的能力,允许以声明的方式来定义调用方式时所需的权限。代码清单 6中给出了对方法调用进行保护的配置文件示例。

0
相关文章