1. 项目目录
2. pom.xml
< dependency> < groupId> org.springframework.boot</ groupId> < artifactId> spring-boot-starter-web</ artifactId> < version> 2.6.3</ version>
</ dependency>
< dependency> < groupId> org.springframework.boot</ groupId> < artifactId> spring-boot-starter-security</ artifactId> < version> 2.6.3</ version>
</ dependency>
3. 创建实体类
LoginForm
package com. cnbai. entity ;
public class LoginForm { private String username; private String password; public String getUsername ( ) { return username; } public void setUsername ( String username) { this . username = username; } public String getPassword ( ) { return password; } public void setPassword ( String password) { this . password = password; }
}
User
package com. cnbai. entity ; import org. springframework. security. core. GrantedAuthority ;
import org. springframework. security. core. authority. SimpleGrantedAuthority ;
import org. springframework. security. core. userdetails. UserDetails ;
import java. util. ArrayList ;
import java. util. Collection ;
public class User implements UserDetails { private String username; private String password; @Override public Collection < ? extends GrantedAuthority > getAuthorities ( ) { ArrayList < SimpleGrantedAuthority > list = new ArrayList < > ( ) ; list. add ( new SimpleGrantedAuthority ( "USER" ) ) ; return list; } @Override public String getPassword ( ) { return password; } @Override public String getUsername ( ) { return username; } @Override public boolean isAccountNonExpired ( ) { return true ; } @Override public boolean isAccountNonLocked ( ) { return true ; } @Override public boolean isCredentialsNonExpired ( ) { return true ; } @Override public boolean isEnabled ( ) { return true ; }
}
4. 创建拦截器
SessionInterceptor
package com. cnbai. intercepter ; import com. cnbai. cache. RequestCache ;
import com. cnbai. cache. SystemCache ;
import org. springframework. web. servlet. HandlerInterceptor ;
import org. springframework. web. servlet. ModelAndView ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import javax. servlet. http. HttpSession ;
public class SessionInterceptor implements HandlerInterceptor { @Override public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request. getHeader ( "token" ) ; if ( token == null ) { return false ; } HttpSession session = SystemCache . getSession ( token) ; if ( session == null ) { return false ; } RequestCache . setSession ( session) ; return true ; } @Override public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { RequestCache . cleanSession ( ) ; } @Override public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System . out. println ( "after..." ) ; }
}
5. 创建配置类
WebConfig
package com. cnbai. config ; import com. cnbai. intercepter. SessionInterceptor ;
import org. springframework. context. annotation. Configuration ;
import org. springframework. web. servlet. config. annotation. InterceptorRegistry ;
import org. springframework. web. servlet. config. annotation. WebMvcConfigurer ;
@Configuration
public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors ( InterceptorRegistry registry) { registry. addInterceptor ( new SessionInterceptor ( ) ) . addPathPatterns ( "/**" ) . excludePathPatterns ( "/login" ) ; }
}
SystemConfig
package com. cnbai. config ; import com. cnbai. cache. SystemCache ;
import org. springframework. boot. CommandLineRunner ;
import org. springframework. context. annotation. Bean ;
import org. springframework. context. annotation. Configuration ;
import org. springframework. core. annotation. Order ;
import org. springframework. security. crypto. bcrypt. BCryptPasswordEncoder ;
import org. springframework. security. crypto. password. PasswordEncoder ;
@Configuration
@Order ( 1 )
public class SystemConfig implements CommandLineRunner { @Override public void run ( String . . . args) throws Exception { SystemCache . init ( ) ; } @Bean public PasswordEncoder passwordEncoder ( ) { return new BCryptPasswordEncoder ( ) ; }
}
DiscoverSecurityConfig
package com. cnbai. config ; import org. springframework. context. annotation. Configuration ;
import org. springframework. security. authentication. AuthenticationManager ;
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. userdetails. UserDetailsService ;
import org. springframework. security. crypto. password. PasswordEncoder ;
import javax. annotation. Resource ;
@Configuration
@EnableWebSecurity
public class DiscoverSecurityConfig extends WebSecurityConfigurerAdapter { @Resource private UserDetailsService userDetailsService; @Resource private PasswordEncoder passwordEncoder; @Override protected void configure ( AuthenticationManagerBuilder auth) throws Exception { auth. userDetailsService ( userDetailsService) . passwordEncoder ( passwordEncoder) ; } @Override public AuthenticationManager authenticationManagerBean ( ) throws Exception { return super . authenticationManager ( ) ; } @Override public void configure ( WebSecurity web) throws Exception { web. ignoring ( ) . antMatchers ( "/resources/**" ) . antMatchers ( "/static/**" ) ; } @Override protected void configure ( HttpSecurity http) throws Exception { http. authorizeHttpRequests ( ) . antMatchers ( "/**" ) . permitAll ( ) . anyRequest ( ) . authenticated ( ) . and ( ) . exceptionHandling ( ) . accessDeniedPage ( "/404" ) . and ( ) . csrf ( ) . disable ( ) ; }
}
6. 创建缓存
SystemCache
package com. cnbai. cache ; import javax. servlet. http. HttpSession ;
import java. util. HashMap ;
import java. util. Map ;
public class SystemCache { public static void init ( ) { SessionCache . SESSION_CACHE . init ( ) ; } public static HttpSession getSession ( String token) { return SessionCache . SESSION_CACHE . getSession ( token) ; } public static void addSession ( String token, HttpSession session) { SessionCache . SESSION_CACHE . add ( token, session) ; } public static void clearSession ( String token) { SessionCache . SESSION_CACHE . clearSession ( token) ; } private enum SessionCache { SESSION_CACHE ; private final Map < String , HttpSession > cache; private void init ( ) { cache = new HashMap < > ( 1 ) ; } private void add ( String token, HttpSession session) { this . cache. put ( token, session) ; } private HttpSession getSession ( String token) { return this . cache. get ( token) ; } private void clearSession ( String token) { this . cache. remove ( token) ; } }
}
RequestCache
package com. cnbai. cache ; import com. cnbai. entity. User ;
import org. springframework. security. core. context. SecurityContextHolder ;
import javax. servlet. http. HttpSession ;
public class RequestCache { private static final ThreadLocal < HttpSession > THREAD_LOCAL = new ThreadLocal < > ( ) ; private static final String CURRENT_USER = "user" ; public static void setSession ( HttpSession httpSession) { THREAD_LOCAL . set ( httpSession) ; } public static HttpSession getHttpSession ( ) { return THREAD_LOCAL . get ( ) ; } public static void cleanSession ( ) { THREAD_LOCAL . remove ( ) ; } public static void setUser ( User user) { getHttpSession ( ) . setAttribute ( CURRENT_USER , user) ; } public static User getUser ( ) { Object principal = SecurityContextHolder . getContext ( ) . getAuthentication ( ) . getPrincipal ( ) ; if ( principal instanceof User ) { return ( User ) principal; } else { return ( User ) getHttpSession ( ) . getAttribute ( CURRENT_USER ) ; } }
}
7. 创建 Service
UserServiceImpl
package com. cnbai. service ; import com. cnbai. cache. RequestCache ;
import com. cnbai. cache. SystemCache ;
import com. cnbai. entity. LoginForm ;
import com. cnbai. entity. User ;
import org. springframework. security. authentication. AuthenticationManager ;
import org. springframework. security. authentication. UsernamePasswordAuthenticationToken ;
import org. springframework. security. core. Authentication ;
import org. springframework. security. core. context. SecurityContextHolder ;
import javax. annotation. Resource ;
import javax. servlet. http. HttpServletRequest ;
import java. util. UUID ;
public class UserServiceImpl { @Resource private AuthenticationManager authenticationManager; public User login ( LoginForm loginForm, HttpServletRequest request) { User userDetail = queryByName ( loginForm. getUsername ( ) ) ; UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken ( userDetail, loginForm. getPassword ( ) ) ; Authentication authenticate = authenticationManager. authenticate ( authenticationToken) ; SecurityContextHolder . getContext ( ) . setAuthentication ( authenticate) ; Object principal = authenticate. getPrincipal ( ) ; if ( principal instanceof User ) { User user = ( User ) principal; RequestCache . setSession ( request. getSession ( ) ) ; RequestCache . setUser ( user) ; } String token = UUID . randomUUID ( ) . toString ( ) . replaceAll ( "-" , "" ) ; SystemCache . addSession ( token, RequestCache . getHttpSession ( ) ) ; return RequestCache . getUser ( ) ; } public void logout ( HttpServletRequest request) { RequestCache . cleanSession ( ) ; SecurityContextHolder . clearContext ( ) ; SystemCache . clearSession ( request. getHeader ( "token" ) ) ; }
}