我的实例是Spring Boot我的项目,轻易一个SpringBoot我的项目都能够,先不启用SpringSecurity。
创立一个demoController,加办法:
@ResponseBody @RequestMapping("wtf") public String wtf(){ return "WTF"; }
运行我的项目,浏览器测试一下:
而后,pom文件退出SpringSecurity的依赖后就启用SpringSecurity了。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
重新启动我的项目,拜访wtf测试一下:
阐明SpringSecurity起作用了,因为Spring Security的默认安全策略是对所有申请都必须通过平安验证,所以申请wtf须要首先通过身份认证能力拜访。这个时候他用的是默认的叫InMemoryUserDetailsManager的用户信息管理器来实现咱们上篇文章所说的用户管理工作的,他的默认用户为user,明码在启动的过程中打印在了控制台:
用这个用户名、明码试一下:
能够拜访:
好的,咱们开始干活。
用户对象Userdetails
首先须要有用户对象,用户对象须要有用户名、明码,SpringSecurity要求用户对象实现接口:
org.springframework.security.core.userdetails。
代码如下,简略一点:
@Componentpublic class User implements UserDetails { private String name; private String password; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return null; } @Override public String getPassword() { return password; } @Override public String getUsername() { return name; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; }}
UserDetailsService
而后须要有咱们本人的UserDetailsService。
创立一个用户service类、实现UserDetailsService接口的loadUserByUsername办法即可。
咱们创立一个用户名 user,明码:123456的用户,示意以后零碎用户只有一个user用户、明码为123456.
@Service@Slf4jpublic class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { log.info("Here we are in MyUserDetailsService===="); User user=new User(); user.setName("user"); user.setPassword("123456"); return user; }}
PasswordEncoder
实现明码解析器PasswordEncoder的encode、matches办法,这两个办法很好了解,encode是对明码明文进行加密的,返回加密后的明码密文,matches办法是用来验密的。
咱们不钻研加密算法,所以也就不加密了,理论利用的时候,我的项目中能够替换encode办法为加密算法即可。
@Servicepublic class MyPasswordEncoder implements PasswordEncoder { @Override public String encode(CharSequence rawPassword) { return rawPassword.toString(); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { return encode(rawPassword).equals(encodedPassword); }}
强调一下,UserDetailsService和PasswordEncoder须要加注解@Service,目标是注入Spring Ioc容器。
重新启动我的项目,这个时候控制台不会再打印下面的那个随机明码串了。
拜访wtf,要求登录:
录入user/123456:
登录胜利了!
阐明下面咱们本人创立的UserDetailsService和PasswordEncoder曾经开始工作了!!!
会不会感觉太简略了点?
简略剖析一下咱们本人实现的这两个类的失效起因。
Spring Security在初始化UsernamePassword...的过程中会通过一个叫 InitializeUserDetailsManagerConfigurer的配置类来初始化咱们上一篇文章说过的AuthenticationProvider,通过上一篇文章咱们晓得绝大部分的用户验证工作都是这个AuthenticationProvider实现的。
咱们简略看一下InitializeUserDetailsManagerConfigurer的configure办法:
@Override public void configure(AuthenticationManagerBuilder auth) throws Exception { if (auth.isConfigured()) { return; } UserDetailsService userDetailsService = getBeanOrNull(UserDetailsService.class); if (userDetailsService == null) { return; } PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class); UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); if (passwordEncoder != null) { provider.setPasswordEncoder(passwordEncoder); } if (passwordManager != null) { provider.setUserDetailsPasswordService(passwordManager); } provider.afterPropertiesSet(); auth.authenticationProvider(provider); }
办法不长,能够看到首先要到Spring Ioc容器中去获取UserDetailsService和PasswordEncoder,如果能获取到的话,就赋值给初始化好的AuthenticationProvider。
因为咱们创立的UserDetailsService和PasswordEncoder都曾经通过注解注入到SpringIoc容器中了,所以,这里就能获取到。后续AuthenticationProvider在用户认证干活的时候能调用到咱们创立的这两个对象就不奇怪了!
上一篇 Spring Security自定义用户认证过程(1)