zoukankan      html  css  js  c++  java
  • spring-security使用-获得当前用户信息(四)

    主要是通过Authentication封装

    接口定义

    public interface Authentication extends Principal, Serializable {
        //用来获取用户的权限。
        Collection<? extends GrantedAuthority> getAuthorities();
        //方法用来获取用户凭证,一般来说就是密码。
        Object getCredentials();
        //方法用来获取用户携带的详细信息,可能是当前请求之类的东西。
        Object getDetails();
        //方法用来获取当前用户,可能是一个用户名,也可能是一个用户对象。
        Object getPrincipal();
        //当前用户是否认证成功。
        boolean isAuthenticated();
    
        void setAuthenticated(boolean var1) throws IllegalArgumentException;
    }

    如何获取

       @GetMapping("/hello")
        public String hello() {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            return "hello";
        }

    getDetails方法

    可以看到打印了用户id和sessionId信息

     @GetMapping("/hello")
        public String hello() {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails();
            System.out.println(details);
            return "hello";
        }

    打印

    org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: C1886FD11CACBAD7387B9273442BC212

    源码

    1.org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#attemptAuthentication

        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            if (this.postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            } else {
                String username = this.obtainUsername(request);
                String password = this.obtainPassword(request);
                if (username == null) {
                    username = "";
                }
    
                if (password == null) {
                    password = "";
                }
    
                username = username.trim();
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                //为authRequest 的detail赋值 UsernamePasswordAuthenticationToken实现了Authentication
                this.setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            }
        }

    2.org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#setDetails

    protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
    
     protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
                //UsernamePasswordAuthenticationToken是通过authenticationDetailsSource 构建的detail数据
                authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
            }

    3.WebAuthenticationDetailsSource的定义

    public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
        public WebAuthenticationDetailsSource() {
        }
    
        public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
            //我们通过Authentication.getDetails()获取的就是WebAuthenticationDetails
            return new WebAuthenticationDetails(context);
        }
    }

    4.WebAuthenticationDetails定义

    public class WebAuthenticationDetails implements Serializable {
        private static final long serialVersionUID = 520L;
        private final String remoteAddress;
        private final String sessionId;
    
        public WebAuthenticationDetails(HttpServletRequest request) {
            //从request获取ip
            this.remoteAddress = request.getRemoteAddr();
            //获取sessionId
            HttpSession session = request.getSession(false);
            this.sessionId = session != null ? session.getId() : null;
        }
    }

    自定义 

    看上面源码我们知道入口是在UsernamePasswordAuthenticationFilter进行Authentication的detail设置的 如何构建detail对象 是委托给AuthenticationDetailsSource默认是WebAuthenticationDetailsSource

    所以我们自定义就要自定义WebAuthenticationDetailsSource和封装数据的Dtail对象

    通过自定优化《spring-security使用-更友好的方式扩展登录AuthenticationProvider(三)》 验证码校验逻辑

    1.自定义的Detail对象

     */
    public class MyWebAuthenticationDetails extends WebAuthenticationDetails {
        //封装提交的验证码信息
        private String code;
        private HttpServletRequest httpServletRequest;
        public MyWebAuthenticationDetails(HttpServletRequest request) {
            super(request);
            //获得验证码
            this.code=request.getParameter("code");
            this.httpServletRequest=request;
        }
    
        /**
         * 增加一个检查验证码的方法
         * @return
         */
        public boolean checkCode(){
            String verify_code = (String) httpServletRequest.getSession().getAttribute("verify_code");
            if (code == null || verify_code == null || !code.equals(verify_code)) {
                throw new AuthenticationServiceException("验证码错误");
            }
            return true;
        }
    
    }

    2.自定义构建对象

    public class MyWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, MyWebAuthenticationDetails> {
        @Override
        public MyWebAuthenticationDetails buildDetails(HttpServletRequest request) {
            return new MyWebAuthenticationDetails(request);
        }
    }

    3.使用自定义的构建对象替换默认的

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .rememberMe()
                    .key("system")
                    .and()
                    .formLogin()
                    .authenticationDetailsSource(new MyWebAuthenticationDetailsSource())
                    .usernameParameter("loginName")
                    .passwordParameter("loginPassword")
                    .defaultSuccessUrl("/hello")
                    .failureForwardUrl("/loginFail")
                    .failureUrl("/login.html")
                    .permitAll()//不拦截
                    .and()
                    .csrf()//记得关闭
                    .disable();
        }
  • 相关阅读:
    LeetCode OJ String to Integer (atoi) 字符串转数字
    HDU 1005 Number Sequence(AC代码)
    HDU 1004 Let the Balloon Rise(AC代码)
    HDU 1003 Max Sum(AC代码)
    012 Integer to Roman 整数转换成罗马数字
    011 Container With Most Water 盛最多水的容器
    010 Regular Expression Matching 正则表达式匹配
    007 Reverse Integer 旋转整数
    006 ZigZag Conversion
    005 Longest Palindromic Substring 最长回文子串
  • 原文地址:https://www.cnblogs.com/LQBlog/p/14236535.html
Copyright © 2011-2022 走看看