|
@@ -0,0 +1,98 @@
|
|
|
+package cn.minbb.edu.config;
|
|
|
+
|
|
|
+import cn.minbb.edu.handler.*;
|
|
|
+import cn.minbb.edu.model.repository.UserRepository;
|
|
|
+import cn.minbb.edu.service.impl.UserServiceImpl;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Configuration;
|
|
|
+import org.springframework.security.authentication.BadCredentialsException;
|
|
|
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
|
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
|
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
|
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
|
+import org.springframework.security.core.session.SessionRegistryImpl;
|
|
|
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
|
+
|
|
|
+@Configuration
|
|
|
+@EnableWebSecurity
|
|
|
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+
|
|
|
+ private Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
|
|
|
+
|
|
|
+ private UserRepository userRepository;
|
|
|
+ private LoginAuthenticationSuccessHandler loginAuthenticationSuccessHandler;
|
|
|
+ private LoginAuthenticationFailureHandler loginAuthenticationFailureHandler;
|
|
|
+ private LogoutSuccessHandler logoutSuccessHandler;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ public WebSecurityConfig(
|
|
|
+ UserRepository userRepository,
|
|
|
+ LoginAuthenticationSuccessHandler loginAuthenticationSuccessHandler,
|
|
|
+ LoginAuthenticationFailureHandler loginAuthenticationFailureHandler,
|
|
|
+ LogoutSuccessHandler logoutSuccessHandler) {
|
|
|
+ this.userRepository = userRepository;
|
|
|
+ this.loginAuthenticationSuccessHandler = loginAuthenticationSuccessHandler;
|
|
|
+ this.loginAuthenticationFailureHandler = loginAuthenticationFailureHandler;
|
|
|
+ this.logoutSuccessHandler = logoutSuccessHandler;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ http.exceptionHandling()
|
|
|
+ .authenticationEntryPoint(new LoginUrlEntryPoint())
|
|
|
+ .accessDeniedHandler(new AccessDenied())
|
|
|
+ .and().csrf().disable().authorizeRequests()
|
|
|
+ .antMatchers("/user/**").access("hasRole('USER')")
|
|
|
+ .antMatchers("/admin/**").access("hasRole('USER') and hasRole('ADMIN')")
|
|
|
+ .antMatchers("/swagger-ui.html").access("hasRole('ADMIN')")
|
|
|
+ .antMatchers("/css/**", "/js/**", "/images/**", "/fonts/*").permitAll()
|
|
|
+ .and().formLogin().loginPage("/sign-in").loginProcessingUrl("/sign-in")
|
|
|
+ // 用户名字段和密码字段
|
|
|
+ .usernameParameter("username").passwordParameter("password")
|
|
|
+ // 登陆成功后跳转的请求和验证失败后跳转的请求
|
|
|
+ .defaultSuccessUrl("/admin").failureUrl("/sign-in?error=true").permitAll()
|
|
|
+ .successHandler(loginAuthenticationSuccessHandler)
|
|
|
+ .failureHandler(loginAuthenticationFailureHandler)
|
|
|
+ .and().logout().logoutUrl("/sign-out").logoutSuccessUrl("").logoutSuccessHandler(logoutSuccessHandler)
|
|
|
+ // 使 Session 失效
|
|
|
+ .invalidateHttpSession(true)
|
|
|
+ // 清除认证信息
|
|
|
+ .clearAuthentication(true).permitAll()
|
|
|
+ // 开启 cookie 存储用户信息
|
|
|
+ .and().rememberMe().rememberMeParameter("remember").rememberMeCookieName("remember")
|
|
|
+ // cookie 有效期为两个星期(秒)
|
|
|
+ .tokenValiditySeconds(1209600)
|
|
|
+ .and().authorizeRequests()
|
|
|
+ .anyRequest().permitAll()
|
|
|
+ // Session 管理
|
|
|
+ .and().sessionManagement()
|
|
|
+ // 系统中同一个账号的登陆数量限制
|
|
|
+ .maximumSessions(1).sessionRegistry(new SessionRegistryImpl())
|
|
|
+ .and().and().headers().frameOptions().disable()
|
|
|
+ .and().authorizeRequests();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
|
|
+ auth.userDetailsService(new UserServiceImpl(userRepository)).passwordEncoder(new BCryptPasswordEncoder() {
|
|
|
+ @Override
|
|
|
+ public String encode(CharSequence rawPassword) {
|
|
|
+ logger.info("加密时待加密的密码 1 = {}", rawPassword);
|
|
|
+ logger.info("加密原始密码 2 = {}", new BCryptPasswordEncoder().encode(rawPassword));
|
|
|
+ return new BCryptPasswordEncoder().encode(rawPassword);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
|
|
+ logger.info("用户输入密码 = {}", rawPassword);
|
|
|
+ logger.info("数据库密码 = {}", encodedPassword);
|
|
|
+ logger.info("用户输入密码加密 = {}", new BCryptPasswordEncoder().encode(rawPassword));
|
|
|
+ if (!encodedPassword.contentEquals(rawPassword))
|
|
|
+ throw new BadCredentialsException("密码错误!");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|