@Service public class UserService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //此处根据用户名在数据库中查找,这里再也不查找,直接返回一个org.springframework.security.core.userdetails.User对象(若是是自定义的User类,须要实现UserDetails接口) return new User(username,new BCryptPasswordEncoder().encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); } }
@Configuration public class BrowserSecurity extends WebSecurityConfigurerAdapter { //引入自定义UserDetailsService @Autowired private UserService userService; //加密 @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } //配置内存认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //设置UserDetailsService以及密码规则 auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); } }
自定义User类实现该接口,该接口主要有以下方法html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义登陆页面登陆</title> </head> <body> <form action="/login" method="post"> <div class="form"> <h3>帐户登陆</h3> <input type="text" placeholder="用户名" name="username" required="required" /></br> <input type="password" placeholder="密码" name="password" required="required" /> <button type="submit">登陆</button> </div> </form> </body> </html>
总体配置以下:java
@Configuration public class BrowserSecurity extends WebSecurityConfigurerAdapter { //引入自定义UserDetailsService @Autowired private UserService userService; //加密 @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } //配置内存认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //设置UserDetailsService以及密码规则 auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); } //配置HttpSecurity @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //受权配置 .antMatchers("/myLogin.html").permitAll().anyRequest().authenticated() .and() //表单配置 .formLogin().loginPage("/myLogin.html").loginProcessingUrl("/login") .and() //默认都会产生一个hiden标签 里面有安全相关的验证 防止请求伪造 这边咱们暂时不须要 可禁用掉 .csrf().disable(); } }
除了登陆页面能够直接访问,其余请求须要跳转到登陆页面完成认证后才能够访问web
总体配置以下:spring
@Configuration public class BrowserSecurity extends WebSecurityConfigurerAdapter { //引入自定义UserDetailsService @Autowired private UserService userService; //加密 @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } //配置内存认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //设置UserDetailsService以及密码规则 auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); } //配置HttpSecurity @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //受权配置 .antMatchers("/myLogin.html").permitAll().anyRequest().authenticated() .and() //表单配置 .formLogin().loginPage("/myLogin.html").loginProcessingUrl("/login") .successHandler(new AuthenticationSuccessHandler() { //登陆成功返回一段json信息 @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { //Authentication authentication 包含用户登陆信息 String name = authentication.getName(); response.setContentType("application/json;charset=utf-8"); PrintWriter out = response.getWriter(); response.setStatus(200); Map<String,Object> map = new HashMap<>(); map.put("status",200); map.put("msg",name); ObjectMapper mapper = new ObjectMapper(); out.write(mapper.writeValueAsString(map)); out.flush(); out.close(); } }) .failureHandler(new AuthenticationFailureHandler() { //登陆失败,根据相关异常返回失败信息 @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { response.setContentType("application/json;charset=utf-8"); PrintWriter out = response.getWriter(); response.setStatus(401); Map<String,Object> map = new HashMap<>(); map.put("status",401); if(e instanceof LockedException){ map.put("msg","帐户被锁定"); }else if(e instanceof BadCredentialsException){ map.put("msg","帐户名或密码错误"); }else if(e instanceof DisabledException){ map.put("msg","帐户被禁用"); }else if(e instanceof AccountExpiredException){ map.put("msg","帐户已过时"); }else if(e instanceof CredentialsExpiredException){ map.put("msg","密码已过时"); }else{ map.put("msg","登陆失败"); } ObjectMapper mapper = new ObjectMapper(); out.write(mapper.writeValueAsString(map)); out.flush(); out.close(); } }) .and() //默认都会产生一个hiden标签 里面有安全相关的验证 防止请求伪造 这边咱们暂时不须要 可禁用掉 .csrf().disable(); } }
@Component public class MyAuthenticationSucessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("application/json;charset=utf-8"); response.getWriter().write(mapper.writeValueAsString(authentication)); } }
@Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException { } }
@Autowired private MyAuthenticationSucessHandler authenticationSucessHandler; @Autowired private MyAuthenticationFailureHandler authenticationFailureHandler; @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() // 表单登陆 .successHandler(authenticationSucessHandler) // 处理登陆成功 .failureHandler(authenticationFailureHandler) // 处理登陆失败 }
登陆成功
数据库
登陆失败
json