本文描述在spring security中如何获取用户信息。分别介绍几种常用的方法实现。
获取当前认证用户(authenticated principal)最简单的方式是通过SecurityContextHolder类的静态方法:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
下面是改进版本代码,获取前首先检查是否存在认证用户:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
String currentUserName = authentication.getName();
return currentUserName;
}
当然,静态调用的缺点是代码的可测试性明显降低。我们继续探索新的方式实现。
在@Controller 注解的bean里,有额外的选项。principal 可以直接作为方法参数,框架会自动赋值。
import java.security.Principal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SecurityController {
@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Principal principal) {
return principal.getName();
}
}
或者也可以使用认证信息:
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SecurityController {
@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Authentication authentication) {
return authentication.getName();
}
}
框架为了尽可能的灵活,Authentication 类的API很方便使用。因此,通过转换可以返回principal对象。
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
System.out.println("User has authorities: " + userDetails.getAuthorities());
最后一种方式直接通过http request:
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SecurityController {
@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserNameSimple(HttpServletRequest request) {
Principal principal = request.getUserPrincipal();
return principal.getName();
}
}
为了充分利用spring的依赖注入功能,可以在在任何地方获取认证信息,不仅仅是@Controller注解的bean,我们通过简单的门面隐藏静态访问:
public interface IAuthenticationFacade {
Authentication getAuthentication();
}
@Component
public class AuthenticationFacade implements IAuthenticationFacade {
@Override
public Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
}
该门面暴露了认证对象并隐藏静态访问代码,让业务解耦并方便测试:
@Controller
public class SecurityController {
@Autowired
private IAuthenticationFacade authenticationFacade;
@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserNameSimple() {
Authentication authentication = authenticationFacade.getAuthentication();
return authentication.getName();
}
}
当前认证用户也可以在jsp页面中获取到。利用spring security标签支持。首先我们需要在页面中定义标签:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
然后,我们可以引用principal:
authenticated as
本文说明在spring应用中如何获取用户信息,开始介绍了通用的静态方法访问机制,后面提供了几种更好的注入方式获取principal。