## 导入maven依赖
org.springframework.boot
spring-boot-starter-security
package com.cloud.common;
import com.cloud.config.filter.CkCodeAuthenticationFilter;
import com.cloud.config.filter.InitialAuthenticationFilter;
import com.cloud.config.filter.JwtAuthenticationFilter;
import com.cloud.config.handler.CustAuthFailHandler;
import com.cloud.config.handler.CustAuthSuccHandler;
import com.cloud.config.provider.OptAuthProvider;
import com.cloud.config.provider.UsernamePasswordAuthProvider;
import com.cloud.sys.dto.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import javax.sql.DataSource;
import java.util.Arrays;
/**
* @author haizhuangbu
* @date 2022/4/28 09:29
* @mark WebConfig
*/
@Configuration
public class WebConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private OptAuthProvider optAuthProvider;
@Autowired
private UsernamePasswordAuthProvider usernamePasswordAuthProvider;
@Autowired
private CustAuthSuccHandler authenticationSuccessHandler;
@Autowired
private CustAuthFailHandler authenticationFailureHandler;
@Autowired
private InitialAuthenticationFilter initialAuthenticationFilter;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private CkCodeAuthenticationFilter ckCodeAuthenticationFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 数据库实现 验证方式
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select USER_NAME,USER_PASS,USER_ENABLE\n" +
"from S_USR where USER_NAME = ?")
.authoritiesByUsernameQuery("\n" +
"select AUTH_ROLE,S_AUTH.USER_NAME\n" +
"from S_AUTH where S_AUTH.USER_NAME = ?")
.passwordEncoder(new MyPasswordEncoder())
.rolePrefix("ADMIN");
auth.authenticationProvider(optAuthProvider)
.authenticationProvider(usernamePasswordAuthProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 表单验证 设置放通路径
http.authorizeRequests()
.mvcMatchers("image/**", "/error", "/image/**", "/file/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
// 设置拦截类
.addFilterBefore(ckCodeAuthenticationFilter, BasicAuthenticationFilter.class)
.addFilterAt(initialAuthenticationFilter, BasicAuthenticationFilter.class)
.addFilterAfter(jwtAuthenticationFilter, BasicAuthenticationFilter.class)
.formLogin()
// 配置成功|失败跳转逻辑
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler);
// .and().csrf().disable();
}
@Override
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}
// 验证过程
package com.cloud.config.filter;
import com.cloud.config.handler.CkCodeFailHandler;
import com.cloud.sys.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author haizhuangbu
* @date 2022/6/6 18:18
* @mark CkCodeAuthenticationFilter
*/
@Component
public class CkCodeAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private CkCodeFailHandler ckCodeFailHandler;
@Autowired
private ProductService webScoketService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
logger.info("================== 执行验证码校验 =======================");
String key = request.getParameter("imgKey");
String value = request.getParameter("imgValue");
ValueOperations str = redisTemplate.opsForValue();
String code = str.get(key);
// assert code != null;
if (code == null || !code.equalsIgnoreCase(value)) {
webScoketService.sendAll(request.getParameter("username") + " : " + "验证码校验失败");
ckCodeFailHandler.onAuthenticationFailure(request, response, new BadCredentialsException("验证码校验错误"));
return;
}
webScoketService.sendAll(request.getParameter("username") + " : " + "验证码校验成功");
chain.doFilter(request, response);
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return !request.getServletPath().equals("/login");
}
}
// 登陆成功逻辑
package com.cloud.config.handler;
import com.alibaba.fastjson.JSONObject;
import com.cloud.common.JwtUtils;
import com.cloud.sys.dto.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Service;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
/**
* @author haizhuangbu
* @date 2022/6/2 22:25
* @mark CustAuthSuccHandler 登录成功逻辑
*/
@Service
public class CustAuthSuccHandler implements AuthenticationSuccessHandler {
private Logger logger = LoggerFactory.getLogger(CustAuthSuccHandler.class);
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
logger.info("================ 执行登录成功逻辑 ===================");
response.setContentType("application/json;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
// 跳转
User user = new User();
user.setAuth(authentication);
String jwt = JwtUtils.createJwt(user);
response.setHeader("authentication", jwt);
logger.info("============== 存储token =======================");
ValueOperations string = redisTemplate.opsForValue();
string.set(jwt, "1", 600, TimeUnit.SECONDS);
HashMap map = new HashMap<>();
map.put("code", HttpStatus.OK);
map.put("success", true);
map.put("message", "loginSuccess");
outputStream.print(JSONObject.toJSONString(map));
outputStream.flush();
outputStream.close();
}
}
// 登陆失败
package com.cloud.config.handler;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Service;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
/**
* @author haizhuangbu
* @date 2022/6/2 22:25
* @mark CustAuthSuccHandler 登录失败逻辑
*/
@Service
public class CustAuthFailHandler implements AuthenticationFailureHandler {
private Logger logger = LoggerFactory.getLogger(CustAuthFailHandler.class);
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
PrintWriter writer = response.getWriter();
// ServletOutputStream outputStream = response.getOutputStream();
HashMap map = new HashMap<>();
map.put("code", HttpStatus.INTERNAL_SERVER_ERROR);
map.put("success", false);
map.put("message", e.getMessage());
writer.print(JSONObject.toJSONString(map));
response.sendRedirect("/login");
writer.flush();
writer.close();
}
}