创建spring boot 工程,加入spring security依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
启动项目,会进入spring security的默认登录页面:
用户名为 user,密码在项目启动过程中会打印在控制台:
新建spring security的配置类,注意要继承WebSecurityConfigurerAdapter类 ,添加注解@Configuration:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//放过所有的静态文件
http.authorizeRequests()
.antMatchers("/", "/*.html", "/css/**", "/js/**", "/vendor/**")
.permitAll().anyRequest().authenticated();
//定义登录表单提交地址
http.formLogin().loginProcessingUrl("/login");
}
}
新建一个控制器配合上面的配置把所有未登录的请求重定向到自定义登录页面:
@Controller
public class LoginPageConfig {
@RequestMapping("/")
public RedirectView loginPage() {
System.out.println("/");
return new RedirectView("/login.html");
}
}
然后在新建自己的自定义登录页面,启动项目,就会访问到自己的自定义登录页面:
这时的用户名还是user密码还是在控制台中,不过表单提交地址要和 http.formLogin().loginProcessingUrl("/login");中的一样。
编写UserDetailsService接口的实现类,在里面写自己的登录逻辑:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private PermissionService permissionService;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
SysUser sysUser = userService.findByUsername(s);
if (sysUser == null) {
throw new AuthenticationCredentialsNotFoundException("用户名不存在");
} else if (sysUser.getStatus() == LoginUser.Status.LOCKED) {
throw new LockedException("用户被锁定,请联系管理员");
} else if (sysUser.getStatus() == LoginUser.Status.DISABLED) {
throw new DisabledException("用户已作废");
}
LoginUser loginUser = new LoginUser();
BeanUtils.copyProperties(sysUser,loginUser);
List<Permission> permissions = permissionService.listByUserId(sysUser.getId());
loginUser.setPermissions(permissions);
return loginUser;
}
}
回到spring security的配置类SecurityConfig,添加:
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
这样就可登录数据库表中用户了。
编写SecurityHandlerConfig,在里面编写自己的登陆成功、登陆失败、退出处理等操作:
@Configuration
public class SecurityHandlerConfig {
/**
* 登陆成功,返回Token
*
* @return
*/
@Bean
public AuthenticationSuccessHandler loginSuccessHandler() {
return new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
//do something
}
};
}
/**
* 登陆失败
*
* @return
*/
@Bean
public AuthenticationFailureHandler loginFailureHandler() {
return new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
//do something
}
};
}
/**
* 未登录,返回401
*
* @return
*/
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
//do something
}
};
}
/**
* 退出处理
*
* @return
*/
@Bean
public LogoutSuccessHandler logoutSussHandler() {
return new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
//do something
}
};
}
}
修改spring security的配置类SecurityConfig:
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private LogoutSuccessHandler logoutSuccessHandler;
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/", "/*.html", "/css/**", "/js/**", "/vendor/**")
.permitAll().anyRequest().authenticated();
http.formLogin().loginProcessingUrl("/login").successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler).and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
}