springsecurity从当前请求对象中获取用户信息
springsecurity 之 登录用户数据的获取
从当前请求对象中获取用户信息
@RequestMapping("/authentication")
public void authentication(Authentication authentication) {
System.out.println("authentication = " + authentication);
}
@RequestMapping("/principal")
public void principal(Principal principal, HttpServletRequest req) {
System.out.println("req.getClass() = " + req.getClass());
System.out.println("principal = " + principal);
}
@RequestMapping("/info")
public void info(HttpServletRequest req) {
String remoteUser = req.getRemoteUser();
Authentication auth = ((Authentication) req.getUserPrincipal());
boolean admin = req.isUserInRole("admin");
System.out.println("remoteUser = " + remoteUser);
System.out.println("auth.getName() = " + auth.getName());
System.out.println("admin = " + admin);
}
SpringMVC中Controller的请求参数都是当前请求HttpServletRequest带来的,Authentication Principal也是HttpServletRequest带来的,在Controller层我们拿到的是HttpServletRequest的实例是Servlet3SecurityContextHolderAwareRequestWrapper
Servlet3SecurityContextHolderAwareRequestWrapper
Servlet3SecurityContextHolderAwareRequestWrapper继承SecurityContextHolderAwareRequestWrapper 主要看一下SecurityContextHolderAwareRequestWrapper
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.security.web.servletapi;
import java.security.Principal;
import java.util.Collection;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper {
private final AuthenticationTrustResolver trustResolver;
private final String rolePrefix;
public SecurityContextHolderAwareRequestWrapper(HttpServletRequest request, String rolePrefix) {
this(request, new AuthenticationTrustResolverImpl(), rolePrefix);
}
public SecurityContextHolderAwareRequestWrapper(HttpServletRequest request, AuthenticationTrustResolver trustResolver, String rolePrefix) {
super(request);
Assert.notNull(trustResolver, "trustResolver cannot be null");
this.rolePrefix = rolePrefix;
this.trustResolver = trustResolver;
}
private Authentication getAuthentication() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return !this.trustResolver.isAnonymous(auth) ? auth : null;
}
public String getRemoteUser() {
Authentication auth = this.getAuthentication();
if (auth != null && auth.getPrincipal() != null) {
return auth.getPrincipal() instanceof UserDetails ? ((UserDetails)auth.getPrincipal()).getUsername() : auth.getPrincipal().toString();
} else {
return null;
}
}
public Principal getUserPrincipal() {
Authentication auth = this.getAuthentication();
return auth != null && auth.getPrincipal() != null ? auth : null;
}
private boolean isGranted(String role) {
Authentication auth = this.getAuthentication();
if (this.rolePrefix != null && role != null && !role.startsWith(this.rolePrefix)) {
role = this.rolePrefix + role;
}
if (auth != null && auth.getPrincipal() != null) {
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
if (authorities == null) {
return false;
} else {
Iterator var4 = authorities.iterator();
GrantedAuthority grantedAuthority;
do {
if (!var4.hasNext()) {
return false;
}
grantedAuthority = (GrantedAuthority)var4.next();
} while(!role.equals(grantedAuthority.getAuthority()));
return true;
}
} else {
return false;
}
}
public boolean isUserInRole(String role) {
return this.isGranted(role);
}
public String toString() {
return "SecurityContextHolderAwareRequestWrapper[ " + this.getRequest() + "]";
}
}
- getAuthentication: 获取当前登录对象Authentication 不是匿名返回 是匿名返回null
- getRemoteUser: 返回当前登录的用户名 即Authentication中的Principal信息
- getUserPrincipal:返回当前登录对象
- isGranted: 判断是否有指定角色
- isUserInRole:调用isGranted
SecurityContextHolderAwareRequestFilter
那么Security如何将默认请求转化为Servlet3SecurityContextHolderAwareRequestWrapper的呢?
是在过滤器链SecurityContextHolderAwareRequestFilter中实现的,SecurityContextHolderAwareRequestFilter主要作用就是对HttpServletRequest请求进行再包装,重写HttpServletRequest和安全管理相关的方法。
SecurityContextHolderAwareRequestFilter源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.security.web.servletapi;
import java.io.IOException;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
private String rolePrefix = "ROLE_";
private HttpServletRequestFactory requestFactory;
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationManager authenticationManager;
private List<LogoutHandler> logoutHandlers;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
public SecurityContextHolderAwareRequestFilter() {
}
public void setRolePrefix(String rolePrefix) {
Assert.notNull(rolePrefix, "Role prefix must not be null");
this.rolePrefix = rolePrefix;
this.updateFactory();
}
public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public void setLogoutHandlers(List<LogoutHandler> logoutHandlers) {
this.logoutHandlers = logoutHandlers;
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
chain.doFilter(this.requestFactory.create((HttpServletRequest)req, (HttpServletResponse)res), res);
}
public void afterPropertiesSet() throws ServletException {
super.afterPropertiesSet();
this.updateFactory();
}
private void updateFactory() {
String rolePrefix = this.rolePrefix;
this.requestFactory = this.createServlet3Factory(rolePrefix);
}
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
Assert.notNull(trustResolver, "trustResolver cannot be null");
this.trustResolver = trustResolver;
this.updateFactory();
}
private HttpServletRequestFactory createServlet3Factory(String rolePrefix) {
HttpServlet3RequestFactory factory = new HttpServlet3RequestFactory(rolePrefix);
factory.setTrustResolver(this.trustResolver);
factory.setAuthenticationEntryPoint(this.authenticationEntryPoint);
factory.setAuthenticationManager(this.authenticationManager);
factory.setLogoutHandlers(this.logoutHandlers);
return factory;
}
}
doFilter方法中调用requestFactory.create方法 该方法直接创建了Servlet3SecurityContextHolderAwareRequestWrapper实例。然后SpringMVC的ServletRequestMethodArgumentResolver的resolveArgument解析出Principal对象 Authentication对象。
总结
从上面的源码分析中,我们可以感受到springsecurity是如何从当前请求对象中获取用户信息的,理解了这一点,我们在使用spring security的时候才能游刃有余,spring security中重要的就是过滤器链,我们还要理解它的责任链的设计模式的思想,而这篇文章中设计的过滤器链就是SecurityContextHolderAwareRequestFilter,它的功能和作用在文章也有介绍,主要作用就是对HttpServletRequest请求进行再包装,重写HttpServletRequest和安全管理相关的方法。
- 点赞
- 收藏
- 关注作者
评论(0)