集成SpringSecurity+后期可加入JWT

目录

自定义认证授权过滤器

1、SpringSecurity内置认证流程

1.1 自定义认证过滤器

1.1 注入对应的bean

1.3 定义SecurityConfig类


自定义认证授权过滤器

1、SpringSecurity内置认证流程

通过研究SpringSecurity内置基于form表单认证的UsernamePasswordAuthenticationFilter过滤器,我们可以仿照自定义认证过滤器:

内置认证过滤器的核心流程:

核心流程梳理如下:

  • 认证过滤器(UsernamePasswordAuthentionFilter)接收form表单提交的账户、密码信息,并封装成UsernamePasswordAuthenticationToken认证凭对象;

  • 认证过滤器调用认证管理器AuthenticationManager进行认证处理;

  • 认证管理器通过调用用户详情服务获取用户详情UserDetails;

  • 认证管理器通过密码匹配器PasswordEncoder进行匹配,如果密码一致,则将用户相关的权限信息一并封装到Authentication认证对象中;

  • 认证过滤器将Authentication认证过滤器放到认证上下文,方便请求从上下文获取认证信息;

    1.1 自定义认证过滤器

    UsernamePasswordAuthentionFilter过滤器继承了模板认证过滤器AbstractAuthenticationProcessingFilter抽象类,我们也可仿照实现:

  • public class MyUserNamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    
        /**
         * 设置构造,传入自定义登录url地址
         * @param defaultFilterProcessesUrl
         */
        public MyUserNamePasswordAuthenticationFilter(String defaultFilterProcessesUrl) {
            super(defaultFilterProcessesUrl);
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
            //判断请求方法必须是post提交,且提交的数据的内容必须是application/json格式的数据
            if (!request.getMethod().equals("POST") ||
                    ! (request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) || request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE))) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            }
            //获取请求参数
            //获取reqeust请求对象的发送过来的数据流
            ServletInputStream in = request.getInputStream();
            //将数据流中的数据反序列化成Map
            HashMap<String,String> loginInfo = new ObjectMapper().readValue(in, HashMap.class);
            String username = loginInfo.get(USER_NAME);
            username = (username != null) ? username : "";
            username = username.trim();
            String password = loginInfo.get(PASSWORD);
            password = (password != null) ? password : "";
            //将用户名和密码信息封装到认证票据对象下
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
            // Allow subclasses to set the "details" property
    		//setDetails(request, authRequest);
            //调用认证管理器认证指定的票据对象
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    
        /**
         * 认证成功处理方法
         * @param request
         * @param response
         * @param chain
         * @param authResult
         * @throws IOException
         * @throws ServletException
         */
        @Override
        protected void successfulAuthentication(HttpServletRequest request,
                                                HttpServletResponse response,
                                                FilterChain chain,
                                                Authentication authResult) throws IOException, ServletException {
            response.getWriter().write("login success 666.....");
        }
    
        /**
         * 认证失败处理方法
         * @param request
         * @param response
         * @param failed
         * @throws IOException
         * @throws ServletException
         */
        @Override
        protected void unsuccessfulAuthentication(HttpServletRequest request,
                                                  HttpServletResponse response,
                                                  AuthenticationException failed) throws IOException, ServletException {
            response.getWriter().write("login failue 999");
        }
    }

    自己定义后要注入对应的bean

  • 1.2 注入对应的bean

  • @Service("userDetailsService")
    public class MyUserDetailServiceImpl implements UserDetailsService {
    
        @Autowired
        private TbUserMapper tbUserMapper;
        /**
         * 使用security当用户认证时,会自动将用户的名称注入到该方法中
         * 然后我们可以自己写逻辑取加载用户的信息,然后组装成UserDetails认证对象
         * @param userName
         * @return 用户的基础信息,包含密码和权限集合,security底层会自动比对前端输入的明文密码
         * @throws UsernameNotFoundException
         */
        @Override
        public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
            //1.根据用户名称获取用户的账户信息
            TbUser dbUser=tbUserMapper.findUserInfoByName(userName);
            //判断该用户是否存在
            if (dbUser==null) {
                throw new UsernameNotFoundException("用户名输入错误!");
            }
            //2.组装UserDetails对象
            //获取当前用户对应的权限集合(自动将以逗号间隔的权限字符串封装到权限集合中)
            List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList(dbUser.getRoles());
            /*
                参数1:账户
                参数2:密码
                参数3:权限集合
             */
            User user = new User(dbUser.getUsername(), dbUser.getPassword(), list);
            return user;
        }
    }

    1.3 定义SecurityConfig类

    配置默认认证过滤器,保证自定义的认证过滤器要在默认的认证过滤器之前;

     /**
         * 配置授权策略
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();//禁用跨站请求伪造
      		http.authorizeRequests()//对资源进行认证处理
        	.antMatchers("/authentication/form").permitAll()//登录路径无需拦截
        	.anyRequest().authenticated();  //除了上述资源外,其它资源,只有 认证通过后,才能有权访问
         	http
              		//坑-过滤器要添加在默认过滤器之前,否则,登录失效
                    .addFilterBefore(myUserNamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    
        @Bean
        public MyUserNamePasswordAuthenticationFilter myUserNamePasswordAuthenticationFilter() throws Exception {
          	//设置默认登录路径
            MyUserNamePasswordAuthenticationFilter myUserNamePasswordAuthenticationFilter =
                    new MyUserNamePasswordAuthenticationFilter("/authentication/form");
            myUserNamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
            return myUserNamePasswordAuthenticationFilter;
        }

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值