|
@@ -0,0 +1,136 @@
|
|
|
+package com.yaoxiang.planning.config
|
|
|
+
|
|
|
+import com.yaoxiang.planning.model.AuthUser
|
|
|
+import com.yaoxiang.planning.service.UserService
|
|
|
+import mu.KotlinLogging
|
|
|
+import org.springframework.beans.factory.annotation.Value
|
|
|
+import org.springframework.context.annotation.Bean
|
|
|
+import org.springframework.context.annotation.Configuration
|
|
|
+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.builders.WebSecurity
|
|
|
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
|
|
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
|
|
+import org.springframework.security.core.Authentication
|
|
|
+import org.springframework.security.core.AuthenticationException
|
|
|
+import org.springframework.security.core.userdetails.UserDetailsService
|
|
|
+import org.springframework.security.core.userdetails.UsernameNotFoundException
|
|
|
+import org.springframework.security.crypto.password.PasswordEncoder
|
|
|
+import org.springframework.security.web.AuthenticationEntryPoint
|
|
|
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
|
|
|
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
|
|
|
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
|
|
+import org.springframework.security.web.util.matcher.RequestMatcher
|
|
|
+import org.springframework.util.DigestUtils
|
|
|
+import javax.annotation.Resource
|
|
|
+import javax.servlet.http.HttpServletRequest
|
|
|
+import javax.servlet.http.HttpServletResponse
|
|
|
+
|
|
|
+private val logger = KotlinLogging.logger {}
|
|
|
+
|
|
|
+@Configuration
|
|
|
+@EnableWebSecurity
|
|
|
+class WebSecurityConfig : WebSecurityConfigurerAdapter() {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private lateinit var userService: UserService
|
|
|
+
|
|
|
+ @Value("\${web.loginPage:/login}")
|
|
|
+ private val loginPage: String? = null
|
|
|
+
|
|
|
+ @Value("\${web.logoutUrl:/logout}")
|
|
|
+ private var logoutUrl: String? = null
|
|
|
+
|
|
|
+ @Value("\${web.permitUrls:/**/*.png}")
|
|
|
+ private lateinit var permitUrls: Array<String>
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ override fun userDetailsService(): UserDetailsService { //覆盖写userDetailsService方法 (1)
|
|
|
+ return UserDetailsService {
|
|
|
+ val optional = userService.findByUsername(it)
|
|
|
+ if (optional.isPresent) {
|
|
|
+ return@UserDetailsService AuthUser(optional.get())
|
|
|
+ }
|
|
|
+ throw UsernameNotFoundException("$it not found")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ fun loginSuccessHandler(): LoginSuccessHandler {
|
|
|
+ return LoginSuccessHandler()
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ fun logoutSuccessHandler(): LogoutSuccessHandler {
|
|
|
+ return LogoutSuccessHandler { _: HttpServletRequest?, rep: HttpServletResponse, authentication: Authentication ->
|
|
|
+ logger.info { "logout success,user=${authentication.principal}" }
|
|
|
+ rep.characterEncoding = "UTF-8"
|
|
|
+ rep.contentType = "application/json"
|
|
|
+ rep.writer.println("{\"ok\":\"1\",\"msg\":\"注销成功\"}")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ fun webAuthenticationDetailsSource(): WebAuthenticationDetailsSource? {
|
|
|
+ return WebAuthenticationDetailsSource()
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ fun authenticationEntryPoint(): AuthenticationEntryPoint? {
|
|
|
+ return AuthenticationEntryPoint { _: HttpServletRequest?, response: HttpServletResponse, _: AuthenticationException? -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED) }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ fun requestMatcher(): RequestMatcher {
|
|
|
+ return RequestMatcher {
|
|
|
+ "XMLHttpRequest" == it.getHeader("X-Requested-With") ||
|
|
|
+ it.getHeader("Accept") != null && it.getHeader("Accept").contains("application/json")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun configure(auth: AuthenticationManagerBuilder) {
|
|
|
+ auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder())
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ fun passwordEncoder(): PasswordEncoder {
|
|
|
+ return object : PasswordEncoder {
|
|
|
+ override fun encode(rawPassword: CharSequence): String {
|
|
|
+ return DigestUtils.md5DigestAsHex((rawPassword as String).toByteArray()).toUpperCase()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun matches(rawPassword: CharSequence, encodedPassword: String): Boolean {
|
|
|
+ return encodedPassword.equals(DigestUtils.md5DigestAsHex((rawPassword as String).toByteArray()), true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun configure(http: HttpSecurity) {
|
|
|
+ http.csrf().disable()
|
|
|
+ http.headers().cacheControl().disable()
|
|
|
+ http.headers().frameOptions().sameOrigin()
|
|
|
+ http.authorizeRequests().antMatchers("/login.html", loginPage).permitAll()
|
|
|
+ http.authorizeRequests().anyRequest().authenticated()
|
|
|
+ http.formLogin().loginPage(loginPage).successHandler(loginSuccessHandler())
|
|
|
+ .authenticationDetailsSource(webAuthenticationDetailsSource())
|
|
|
+ http.logout().logoutUrl(logoutUrl).logoutRequestMatcher(AntPathRequestMatcher(logoutUrl))
|
|
|
+ .deleteCookies("JSESSIONID")
|
|
|
+ .logoutSuccessHandler(logoutSuccessHandler())
|
|
|
+ http.sessionManagement().invalidSessionUrl(loginPage)
|
|
|
+
|
|
|
+ http.exceptionHandling().defaultAuthenticationEntryPointFor(authenticationEntryPoint(), requestMatcher())
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ override fun configure(web: WebSecurity) {
|
|
|
+ web.ignoring().antMatchers("/resources/**", "/static/**")
|
|
|
+ web.ignoring().antMatchers("/**/*.js", "/lang/*.json", "/**/*.css", "/**/*.map", "/**/*.png",
|
|
|
+ "/**/*.jpg", "/**/*.woff", "/**/*.ttf", "/*.ico")
|
|
|
+ web.ignoring().antMatchers(*permitUrls)
|
|
|
+ web.ignoring().antMatchers("/doc.html")
|
|
|
+ web.ignoring().antMatchers("/open/**")
|
|
|
+ }
|
|
|
+}
|