赞
踩
目录
通过研究SpringSecurity内置基于form表单认证的UsernamePasswordAuthenticationFilter过滤器,我们可以仿照自定义认证过滤器:
内置认证过滤器的核心流程:
核心流程梳理如下:
认证过滤器(UsernamePasswordAuthentionFilter)接收form表单提交的账户、密码信息,并封装成UsernamePasswordAuthenticationToken认证凭对象;
认证过滤器调用认证管理器AuthenticationManager进行认证处理;
认证管理器通过调用用户详情服务获取用户详情UserDetails;
认证管理器通过密码匹配器PasswordEncoder进行匹配,如果密码一致,则将用户相关的权限信息一并封装到Authentication认证对象中;
认证过滤器将Authentication认证过滤器放到认证上下文,方便请求从上下文获取认证信息;
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
- @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;
- }
- }
配置默认认证过滤器,保证自定义的认证过滤器要在默认的认证过滤器之前;
- /**
- * 配置授权策略
- * @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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。