在第一篇基础上,增加了出错处理
1、pom.xml中添加
<!-- 验证码kaptcha-->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
2、在WebSecurityConfig中添加
注意:相比于第一篇,修改了出错处理!!!
同时添加了出错处理
package com.chenclass.xabest.config;
import com.chenclass.xabest.filter.OpenIdAuthenticationFilter;
import com.chenclass.xabest.security.CustomUserService;
import org.springframework.beans.factory.annotation.Autowired;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity // 注解开启Spring Security的功能
//WebSecurityConfigurerAdapter:重写它的方法来设置一些web的安全西街
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserService customUserService;
@Autowired
MyAuthenctiationFailureHandler myAuthenctiationFailureHandler;
/*@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
*/
@Bean
public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder();
}
//md5不够安全,spring5 已结删除
// @Bean
// public Md5PasswordEncoder passwordEncoder() { return new Md5PasswordEncoder(); }
// public Md5PasswordEncoder md5 = new Md5PasswordEncoder();
protected void configure(HttpSecurity http) throws Exception {
http.addFilter(openIdAuthenticationFilter());
http
.authorizeRequests() //定义哪些url需要保护,哪些url不需要保护
.antMatchers("/layuiadmin/**","/reg/**","/defaultKaptcha**","/login**").permitAll() //定义不需要认证就可以访问
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login") //定义当需要用户登录时候,转到的登录页面
.permitAll()
.and().logout().logoutSuccessUrl("/login") //注销
.and()
.logout()
.permitAll();
// .and().cors(); // 这句非常重要了;
http.csrf().disable(); //
http.formLogin()
.defaultSuccessUrl("/index")
.failureHandler(myAuthenctiationFailureHandler);
// .failureUrl("/login?error=true");
http.headers().frameOptions().disable(); //解决 in a frame because it set 'X-Frame-Options' to 'deny'.陈锡爱20190511
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
/*BCryptPasswordEncoder passwordEncoder =new BCryptPasswordEncoder();
String password = passwordEncoder.encode("111");
auth
.inMemoryAuthentication()
// .withUser("user").password("111").roles("USER");
.withUser("user").password(password).roles("USER");
*/
auth.userDetailsService(customUserService).passwordEncoder(passwordEncoder());
//在内存中创建了一个用户,该用户的名称为user,密码为password,用户角色为USER
}
/**
* 自定义登陆验证接口
*/
public OpenIdAuthenticationFilter openIdAuthenticationFilter() throws Exception {
OpenIdAuthenticationFilter openIdAuthenticationFilter = new OpenIdAuthenticationFilter();
openIdAuthenticationFilter.setAuthenticationManager(authenticationManager());
//只有post请求才拦截
openIdAuthenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
//openIdAuthenticationFilter.setAuthenticationSuccessHandler(securityAuthenticationSuccessHandler);
//openIdAuthenticationFilter.setAuthenticationFailureHandler(securityAuthenticationFailureHandler);
// openIdAuthenticationFilter.setAuthenticationFailureHandler(MyAuthenctiationFailureHandler);
return openIdAuthenticationFilter;
}
}
3、添加出错处理
package com.chenclass.xabest.config;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component("myAuthenctiationFailureHandler")
public class MyAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
/* private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
*/
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
// logger.info("进入认证失败处理类");
// response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.setContentType("application/json;charset=UTF-8");
//转发到login
// request.getRequestDispatcher("/login?error="+exception.getMessage()).forward(request, response);
// response.sendRedirect("/login?error="+objectMapper.writeValueAsString(exception.getMessage()));
String m_strmessage = exception.getMessage();
if(m_strmessage.equals("jiaoyanmaerror")) {
response.sendRedirect("/login?codeerror=true");
}
else
{
response.sendRedirect("/login?error=true");
}
return;
}
}
4、添加KaptchaConfig
package com.chenclass.xabest.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
@Component
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha(){
com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.image.width", "110");
properties.setProperty("kaptcha.image.height", "40");
properties.setProperty("kaptcha.textproducer.font.size", "30");
properties.setProperty("kaptcha.session.key", "code");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
5、添加CodeController
package com.chenclass.xabest.controller;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
@Controller
public class CodeController {
@Autowired
private DefaultKaptcha captchaProducer;
@RequestMapping("/defaultKaptcha")
public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
//生成验证码
String capText = captchaProducer.createText();
session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
//向客户端写出
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
6、添加OpenIdAuthenticationFilter
注意:相比于第一篇,修改了出错处理!!!
package com.chenclass.xabest.filter;
import com.chenclass.xabest.config.MyAuthenctiationFailureHandler;
import com.chenclass.xabest.utils.CodeUtil;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class OpenIdAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
// @Autowired
// private RefactorSysUserService sysUserService;
public OpenIdAuthenticationFilter() {
// AntPathRequestMatcher requestMatcher = new AntPathRequestMatcher("/login", "POST");
// this.setRequiresAuthenticationRequestMatcher(requestMatcher);
// this.setAuthenticationManager(getAuthenticationManager());
this.setAuthenticationFailureHandler(new MyAuthenctiationFailureHandler());
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String chen = request.getParameter("username");
String verify = request.getParameter("vrifyCode");
int chen1;
if (!CodeUtil.checkVerifyCode(request)) {
//出错
chen1 =2;
System.out.println("jiaoyanmaerror");
throw new AuthenticationServiceException("jiaoyanmaerror" );
} else {
//正确
chen1 =3;
}
return super.attemptAuthentication(request, response);
}
}
7、添加工具类CodeUtil
package com.chenclass.xabest.utils;
import javax.servlet.http.HttpServletRequest;
public class CodeUtil {
/**
* 将获取到的前端参数转为string类型
* @param request
* @param key
* @return
*/
public static String getString(HttpServletRequest request, String key) {
try {
String result = request.getParameter(key);
if(result != null) {
result = result.trim();
}
if("".equals(result)) {
result = null;
}
return result;
}catch(Exception e) {
return null;
}
}
/**
* 验证码校验
* @param request
* @return
*/
public static boolean checkVerifyCode(HttpServletRequest request) {
//获取生成的验证码
String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
//获取用户输入的验证码
String verifyCodeActual = CodeUtil.getString(request, "vrifyCode");
if(verifyCodeActual == null ||!verifyCodeActual.equals(verifyCodeExpected)) {
return false;
}
return true;
}
}
8、在login页面中添加
相比于第1篇,添加了用户名和密码,校验码出错的提示
<div class="layui-form-item">
<span class ="help-block" style="color:red" th:if="${param.error}" th:text="用户或密码错误,请重新输入!"></span>
<span class ="help-block" style="color:red" th:if="${param.codeerror}" th:text="校验码错误,请仔细检查!"></span>
</div>
9、校验成功和失败的处理还没有写,相比于第1篇,在上面的OpenIdAuthenticationFilter中已经补上了