在上一篇文章SpringSecurity实现简单的用户认证中,已经实现了自定义的安全配置类SecurityConfig(继承了WebSecurityConfigurerAdapter),要实现自定义的登录页,需要覆写其中的config(HttpSecurity http)方法和configure(AuthenticationManagerBuilder auth)方法:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/toLogin")
.loginProcessingUrl("/log")
.defaultSuccessUrl("/main")
.failureForwardUrl("/failed")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/", "/index", "/login", "/css/*", "/js/*", "/img/*")
.permitAll()
.anyRequest()
.authenticated()
.and().csrf().disable();
}
其中loginPage中的参数值表示自定义登录页的请求url,并不是登录页面名,处理该请求的controller的方法为:
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
loginProcessingUrl中的值表示登录表单提交的请求url,要与html中的表单的action保持一致,这个请求url可以不用写具体的controller,因为SpringSecurity会帮你验证登录。
defaultSuccessUrl中的值表示登录成功后跳转的请求url,failureForwardUrl中的值表示登录失败后跳转的请求url,这里可以自定义任意的请求,然后写个controller实现,不再具体展示。
后面的antMatchers方法是为了过滤静态资源,否则页面样式会丢失,另外还过滤了/、/index、/login这些请求,这些请求也都会跳转到登录页。最后一定要禁用csrf,否则SpringSecurity的认证授权功能可能不会生效。
通过以上步骤就可以实现自定义的登录页,而不是使用SpringSecurity默认登录页。接下来需要通过查询数据库实现登录功能。之前的用户已经在loadUserByUsername方法中设置好了,见上一篇文章SpringSecurity实现简单的用户认证 。接上一篇文章,为了查询数据库中的用户,需要在MyUserDetailsService类中设置MyUserMapper的属性,MyUserMapper是MyUser类的数据库访问类,而MyUser类是自定义的用户类,里面存有用户名、密码和权限:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyUser {
private String username;
private String password;
private String role;
}
MyUserMapper中就一个方法,根据用户名查用户:
@Mapper
@Repository
public interface MyUserMapper {
MyUser findByUsername(String username);
}
具体实现在MyUserMapper.xml中:
<mapper namespace="com.example.mapper.MyUserMapper">
<select id="findByUsername" resultType="MyUser" parameterType="string">
select * from user where username = #{username}
</select>
</mapper>
然后修改MyUserDetailsService中的loadUserByUsername方法:
@Autowired
MyUserMapper myUserMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MyUser user = myUserMapper.findByUsername(username);
List<GrantedAuthority> list = new ArrayList<>();
if (!StringUtils.isEmpty(user.getRole())) {
list = AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRole());
}
return new User(user.getUsername(), new BCryptPasswordEncoder().encode(user.getPassword()), list);
}
loadUserByUsername方法中就实现了查询数据库获取用户的功能,其中还获取了权限。以上步骤的前提是SpringBoot整合了MyBatis,可以参考SpringBoot整合Mybatis。
在数据库中往表user里预制一些数据,然后启动项目,就可以验证登录功能。只有user表中预制了的用户才能登录成功,如果是其他用户,则会登录失败。