当前位置: 首页 > 后端技术 > Java

SpringSecurity自定义用户认证流程(二)

时间:2023-04-02 02:08:08 Java

我的例子是一个SpringBoot项目,任何SpringBoot项目都可以,先不要启用SpringSecurity。创建一个demoController并添加方法:@ResponseBody@RequestMapping("wtf")publicStringwtf(){return"WTF";}运行项目,在浏览器中测试:然后,在pom文件中添加SpringSecurity依赖后,SpringSecurity就会被启用。org.springframework.bootspring-boot-starter-security重启项目,访问wtf测试一下:说明SpringSecurity可以用了,因为SpringSecurity默认的安全策略是所有请求都必须通过安全验证,所以请求wtf需要通过身份认证才能访问。这个时候他使用默认的用户信息管理器InMemoryUserDetailsManager来完成我们在上一篇文章中提到的用户管理工作。他的默认用户是user,启动时在控制台打印密码:使用这个Username,password试试看:可访问:OK,开始工作吧。用户对象Userdetails首先需要有一个用户对象,用户对象需要有用户名和密码。SpringSecurity需要用户对象实现接口:org.springframework.security.core.userdetails。代码如下,简单一点:@ComponentpublicclassUserimplementsUserDetails{privateStringname;私有字符串密码;@Override公共集合getAuthorities(){返回null;}@OverridepublicStringgetPassword(){返回密码;}}@OverridepublicbooleanisAccountNonExpired(){返回真;}@OverridepublicbooleanisAccountNonLocked(){返回真;}@OverridepublicbooleanisCredentialsNonExpired(){returnveride;publicbooleanisEnabled(){返回真;}}UserDetailsS??ervice然后需要有我们自己的UserDetailsS??ervice。创建用户服务类,实现UserDetailsS??ervice接口的loadUserByUsername方法。我们创建一个用户,用户名user,密码:123456,表示当前系统用户只有一个用户用户,密码123456。.info("这里是MyUserDetailsS??ervice====");用户user=newUser();user.setName("用户");user.setPassword("123456");返回用户;}}PasswordEncoder实现密码解析器PasswordEncoder的encode和matches方法很好理解。Encode对密码明文进行加密,返回加密后的密码密文。matches方法用于验证密码。我们不研究加密算法,所以不加密。在实际应用中,可以在项目中用加密算法代替encode方式。@Servicepublic类MyPasswordEncoder实现PasswordEncoder{@OverridepublicStringencode(CharSequencerawPassword){returnrawPassword.toString();}@Overridepublicbooleanmatches(CharSequencerawPassword,StringencodedPassword){returnencode(rawPassword).equals(encoded);}}强调UserDetailsS??ervice和PasswordEncoder需要注解@Service才能注入到SpringIoc容器中。重启项目,此时控制台将不再打印上面的随机密码字符串。访问wtf需要登录:输入user/123456:登录成功!这意味着我们上面创建的UserDetailsS??ervice和PasswordEncoder已经开始工作了!!!目标达成,使命达成!!!是不是觉得太简单了?下面简单分析一下我们自己实现的这两个类有效的原因。在初始化UsernamePasswordAuthenticationFilter的过程中,SpringSecurity会通过一个名为InitializeUserDetailsManagerConfigurer的配置类来初始化我们在上一篇文章中提到的AuthenticationProvider。通过上一篇我们知道大部分的用户验证工作都是由这个AuthenticationProvider完成的。我们简单单看一下InitializeUserDetailsManagerConfigurer的配置方法:@Overridepublicvoidconfigure(AuthenticationManagerBuilderauth)throwsException{if(auth.isConfigured()){return;}UserDetailsS??erviceuserDetailsS??ervice=getBeanOrNull(UserDetailsS??ervice.class);如果(userDetailsS??ervice==null){返回;}PasswordEncoderpasswordEncoder=getBeanOrNull(PasswordEncoder.class);UserDetailsPasswordServicepasswordManager=getBeanOrNull(UserDetailsPasswordService.class);DaoAuthenticationProvider提供者=newDaoAuthenticationProvider();provider.setUserDetailsS??ervice(userDetailsS??ervice);if(passwordEncoder!=null){provider.setPasswordEncoder(passwordEncoder);}if(passwordManager!=null){provider.setUserDetailsPasswordService(passwordManager);}provider.afterPropertiesSet();auth.authenticationProvider(提供商);}方法不长。可以看到首先要到SpringIoc容器中获取UserDetailsS??ervice和PasswordEncoder。如果可以获取,则将其赋值给初始化的AuthenticationProvider。因为我们创建的UserDetailsS??ervice和PasswordEncoder已经通过注解注入到SpringIoc容器中,所以可以在这里获取。难怪AuthenticationProvider可以在用户认证工作的时候调用我们创建的这两个对象!上一篇SpringSecurity自定义用户认证流程(一)下一篇SpringSecurity+JWT