springsecurity从当前请求对象中获取用户信息

简介: 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和安全管理相关的方法。

相关文章
|
8月前
|
Java 测试技术 API
【SpringMVC】参数传递与用户请求和响应(上)
【SpringMVC】参数传递与用户请求和响应(上)
45 0
|
2月前
|
前端开发 Java Spring
SpringBoot通过拦截器和JWT令牌实现登录验证
该文介绍了JWT工具类、匿名访问注解、JWT验证拦截器的实现以及拦截器注册。使用`java-jwt`库生成和验证JWT,JwtUtil类包含generateToken和verifyToken方法。自定义注解`@AllowAnon`允许接口匿名访问。JwtInterceptor在Spring MVC中拦截请求,检查JWT令牌有效性。InterceptorConfig配置拦截器,注册并设定拦截与排除规则。UserController示例展示了注册、登录(允许匿名)和需要验证的用户详情接口。
228 1
|
8月前
|
JSON 前端开发 Java
【SpringMVC】参数传递与用户请求和响应(下)
【SpringMVC】参数传递与用户请求和响应(下)
53 0
|
9月前
|
JSON 安全 搜索推荐
​SpringSecurity-5-自定义登录验证
​SpringSecurity-5-自定义登录验证
102 0
|
SQL 安全 Java
SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证
SpringSecurity是一个用于Java 企业级应用程序的安全框架,主要包含用户认证和用户授权两个方面.相比较Shiro而言,Security功能更加的强大,它可以很容易地扩展以满足更多安全控制方面的需求,但也相对它的学习成本会更高,两种框架各有利弊.实际开发中还是要根据业务和项目的需求来决定使用哪一种.
SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证
|
前端开发 数据库 开发者
根据 token 获取用户信息(接口) | 学习笔记
快速学习根据 token 获取用户信息(接口)
1002 0
无token实现登录拦截
无token实现登录拦截
无token实现登录拦截
|
存储 JSON 安全
10-SpringSecurity:JWT及无状态服务
10-SpringSecurity:JWT及无状态服务
313 0
10-SpringSecurity:JWT及无状态服务
|
前端开发 Java 数据安全/隐私保护
3-SpringSecurity:自定义Form表单
3-SpringSecurity:自定义Form表单
119 0
3-SpringSecurity:自定义Form表单
|
JSON 算法 前端开发
JWT+Interceptor实现无状态登录和鉴权(一)
JWT+Interceptor实现无状态登录和鉴权(一)
292 0