package com.ks.app.config;
|
|
import com.google.code.kaptcha.Producer;
|
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
import com.google.code.kaptcha.util.Config;
|
import com.ks.app.entity.AdminUser;
|
import com.ks.app.service.inter.AdminUserService;
|
import net.sf.json.JSONObject;
|
import org.omg.CORBA.SystemException;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.context.annotation.Bean;
|
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
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.core.Authentication;
|
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.userdetails.UserDetails;
|
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.authentication.AuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.yeshi.utils.StringUtil;
|
|
import javax.annotation.Resource;
|
import javax.servlet.FilterChain;
|
import javax.servlet.ServletException;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpSession;
|
import java.io.IOException;
|
import java.util.Properties;
|
|
@EnableWebSecurity
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
private Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
|
|
@Resource
|
private AdminUserService adminUserService;
|
|
private final String LOGIN_PROCESSING_URL = "/admin/api/login";
|
|
//图形验证码配置
|
@Bean
|
public Producer captcha() {
|
Properties properties = new Properties();
|
//图片的宽高
|
properties.setProperty("kaptcha.image.width", "150");
|
properties.setProperty("kaptcha.image.height", "50");
|
//字符集
|
properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
//字符长度
|
properties.setProperty("kaptcha.textproducer.char.length", "4");
|
|
String color = "24,159,146";
|
|
//边框颜色
|
properties.setProperty("kaptcha.border.color", color);
|
//字体颜色
|
properties.setProperty("kaptcha.textproducer.font.color", color);
|
//干扰颜色
|
properties.setProperty("kaptcha.noise.color", color);
|
|
|
Config config = new Config(properties);
|
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
defaultKaptcha.setConfig(config);
|
return defaultKaptcha;
|
}
|
|
|
public class VerificationCodeException extends AuthenticationException {
|
public VerificationCodeException() {
|
super("图形验证码校验失败");
|
}
|
}
|
|
|
//验证码过滤器
|
class VerificationCodeFilter extends OncePerRequestFilter {
|
private AuthenticationFailureHandler authenticationFailureHandler = new AuthenticationFailureHandler() {
|
@Override
|
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
|
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("code", 11);
|
jsonObject.put("msg", "验证码错误");
|
httpServletResponse.getWriter().print(jsonObject);
|
}
|
};
|
|
@Override
|
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
if (!LOGIN_PROCESSING_URL.equalsIgnoreCase(httpServletRequest.getRequestURI())) {
|
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
} else {
|
try {
|
verificationCode(httpServletRequest);
|
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
} catch (VerificationCodeException e) {
|
authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
|
}
|
}
|
}
|
|
private void verificationCode(HttpServletRequest httpServletRequest) throws VerificationCodeException {
|
String requestCode = httpServletRequest.getParameter("captcha");
|
HttpSession httpSession = httpServletRequest.getSession();
|
String captcha = httpSession.getAttribute("captcha") + "";
|
httpSession.removeAttribute("captcha");
|
if (StringUtil.isNullOrEmpty(captcha) || StringUtil.isNullOrEmpty(requestCode) || !captcha.equalsIgnoreCase(requestCode)) {
|
throw new VerificationCodeException();
|
}
|
|
|
}
|
}
|
|
|
@Override
|
protected void configure(HttpSecurity http) throws Exception {
|
http.headers().frameOptions().disable();
|
http.authorizeRequests()
|
.antMatchers("/admin/api/captcha.jpg*").permitAll()
|
.antMatchers("/admin/api/**", "/index.html").authenticated()
|
.and()
|
.formLogin()
|
//自定义登录界面
|
.loginPage("/login.html")
|
//处理登录逻辑的url
|
.loginProcessingUrl(LOGIN_PROCESSING_URL)
|
//登录成功后的跳转
|
.successHandler(new AuthenticationSuccessHandler() {
|
@Override
|
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
|
logger.info("successHandler");
|
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("code", 0);
|
jsonObject.put("msg", "登录成功");
|
httpServletResponse.getWriter().print(jsonObject);
|
}
|
})
|
//登录失败后的处理
|
.failureHandler(new AuthenticationFailureHandler() {
|
@Override
|
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
|
logger.info("failureHandler");
|
httpServletResponse.setContentType("application/json;charset=UTF-8");
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("code", 1);
|
jsonObject.put("msg", e.getMessage());
|
httpServletResponse.getWriter().print(jsonObject);
|
}
|
})
|
.permitAll()
|
.and()
|
//退出登录
|
.logout().logoutUrl("/admin/api/logout").logoutSuccessHandler(new LogoutSuccessHandler() {
|
@Override
|
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
|
logger.info("onLogoutSuccess");
|
}
|
})
|
.and()
|
.csrf().disable()
|
.rememberMe().userDetailsService(new MyUserDetailsService());
|
http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);
|
}
|
|
@Override
|
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
auth.authenticationProvider(new MyAuthenticationProvider(new MyUserDetailsService(), new PasswordEncoder() {
|
@Override
|
public String encode(CharSequence charSequence) {
|
return charSequence.toString();
|
}
|
|
@Override
|
public boolean matches(CharSequence charSequence, String s) {
|
return s.equalsIgnoreCase(charSequence.toString());
|
}
|
}));
|
|
}
|
|
class MyUserDetailsService implements UserDetailsService {
|
|
@Override
|
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
|
AdminUser adminUser = null;
|
if (!StringUtil.isNullOrEmpty(s)) {
|
adminUser = adminUserService.selectByAccount(s);
|
} else {
|
throw new RuntimeException("请填写用户名");
|
}
|
if (null != adminUser) {
|
return adminUser;
|
} else {
|
throw new RuntimeException("该用户不存在");
|
}
|
|
|
}
|
|
|
}
|
|
class MyAuthenticationProvider extends DaoAuthenticationProvider {
|
|
public MyAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
|
this.setUserDetailsService(userDetailsService);
|
this.setPasswordEncoder(passwordEncoder);
|
}
|
|
@Override
|
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
|
if (usernamePasswordAuthenticationToken.getCredentials() == null) {
|
throw new BadCredentialsException("密码不能为空");
|
}
|
String pwd = StringUtil.Md5(usernamePasswordAuthenticationToken.getCredentials().toString());
|
if (!pwd.equalsIgnoreCase(userDetails.getPassword())) {
|
throw new BadCredentialsException("密码错误");
|
}
|
}
|
}
|
|
}
|