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"));
}
}