merge
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.xwbing.util.captcha;
|
||||
|
||||
import com.xwbing.constant.CommonConstant;
|
||||
import com.xwbing.util.CommonDataUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -9,6 +8,7 @@ import javax.imageio.ImageIO;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -33,10 +33,9 @@ public class CaptchaServlet extends HttpServlet {
|
||||
CaptchaUtil tool = new CaptchaUtil();
|
||||
StringBuffer code = new StringBuffer();
|
||||
BufferedImage image = tool.genRandomCodeImage(code);
|
||||
// HttpSession session = req.getSession();
|
||||
// session.removeAttribute(CommonConstant.KEY_CAPTCHA);
|
||||
// session.setAttribute(CommonConstant.KEY_CAPTCHA, code.toString());
|
||||
CommonDataUtil.setToken(CommonConstant.KEY_CAPTCHA, code.toString());
|
||||
HttpSession session = req.getSession();
|
||||
session.removeAttribute(CommonConstant.KEY_CAPTCHA);
|
||||
session.setAttribute(CommonConstant.KEY_CAPTCHA, code.toString());
|
||||
// 将内存中的图片通过流形式输出到客户端
|
||||
OutputStream out = res.getOutputStream();
|
||||
ImageIO.write(image, "JPEG", out);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
jdbc.driver=com.mysql.jdbc.Driver
|
||||
jdbc.url=jdbc:mysql://127.0.0.1:3306/springboot2?useUnicode=true&characterEncoding=utf8
|
||||
jdbc.username=root
|
||||
jdbc.password=
|
||||
jdbc.password=xwbing
|
||||
# 初始化大小,最小,最大
|
||||
jdbc.initSize=1
|
||||
jdbc.minIdle=3
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.xwbing.configuration;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.xwbing.handler.LoginInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -29,7 +28,7 @@ public class DispatcherServletConfig extends WebMvcConfigurerAdapter {
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
//拦截器1:登录判断
|
||||
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
|
||||
// registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
|
||||
// registry.addInterceptor(new LoginInterceptor())
|
||||
// .addPathPatterns("/**").excludePathPatterns("/user/login", "/servlet/captchaCode", "/swagger-ui.html");
|
||||
//拦截器2...
|
||||
|
||||
@@ -108,25 +108,10 @@ public class SysUserControl {
|
||||
@LogInfo("登录")
|
||||
@ApiOperation(value = "登录", response = RestMessageVo.class)
|
||||
@PostMapping("login")
|
||||
public JSONObject login(HttpServletRequest request, @RequestParam String userName, @RequestParam String passWord, @RequestParam String checkCode) {
|
||||
public JSONObject login(HttpServletRequest request, @RequestParam String userName, @RequestParam String passWord, @RequestParam String checkCode, boolean rememberMe) {
|
||||
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) {
|
||||
return JsonResult.toJSONObj("用户名或密码不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(checkCode)) {
|
||||
return JsonResult.toJSONObj("请输入验证码");
|
||||
}
|
||||
RestMessage login = sysUserService.login(request, userName, passWord, checkCode);
|
||||
return JsonResult.toJSONObj(login);
|
||||
}
|
||||
|
||||
@LogInfo("登录")
|
||||
@ApiOperation(value = "登录", response = RestMessageVo.class)
|
||||
@PostMapping("login2")
|
||||
public JSONObject login2(HttpServletRequest request, @RequestParam String userName, @RequestParam String passWord, @RequestParam String checkCode, boolean rememberMe) {
|
||||
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) {
|
||||
return JsonResult.toJSONObj("用户名或密码不能为空");
|
||||
}
|
||||
SysUser user = sysUserService.getByUserName(userName);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
String ip = IpUtil.getIpAddr(request);
|
||||
UsernamePasswordCaptchaToken token = new UsernamePasswordCaptchaToken(userName, passWord.toCharArray(), rememberMe, ip, checkCode);
|
||||
@@ -135,7 +120,7 @@ public class SysUserControl {
|
||||
//保存登录信息
|
||||
SysUserLoginInOut loginInOut = new SysUserLoginInOut();
|
||||
loginInOut.setCreateTime(new Date());
|
||||
loginInOut.setUserId(user.getId());
|
||||
loginInOut.setUserId("");
|
||||
loginInOut.setInoutType(CommonEnum.LoginInOutEnum.IN.getValue());
|
||||
loginInOut.setIp(ip);
|
||||
RestMessage save = loginInOutService.save(loginInOut);
|
||||
@@ -150,14 +135,6 @@ public class SysUserControl {
|
||||
@ApiOperation(value = "登出", response = RestMessageVo.class)
|
||||
@GetMapping("logout")
|
||||
public JSONObject logout(HttpServletRequest request) {
|
||||
RestMessage logout = sysUserService.logout(request);
|
||||
return JsonResult.toJSONObj(logout);
|
||||
}
|
||||
|
||||
@LogInfo("登出")
|
||||
@ApiOperation(value = "登出", response = RestMessageVo.class)
|
||||
@GetMapping("logout2")
|
||||
public JSONObject logout2(HttpServletRequest request) {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
if (subject != null && subject.getPrincipals() != null) {
|
||||
SysUser sysUser = (SysUser) subject.getPrincipals().getPrimaryPrincipal();
|
||||
@@ -173,7 +150,7 @@ public class SysUserControl {
|
||||
}
|
||||
}
|
||||
}
|
||||
return JsonResult.toJSONObj(new Object(),"登出成功");
|
||||
return JsonResult.toJSONObj(new Object(), "登出成功");
|
||||
}
|
||||
|
||||
@LogInfo("修改密码")
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.xwbing.handler;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.xwbing.exception.BusinessException;
|
||||
import com.xwbing.util.JsonResult;
|
||||
import com.xwbing.util.captcha.CaptchaException;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
@@ -50,11 +52,19 @@ public class GlobalExceptionHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* CompletableFuture完成结果或任务过程中出现的异常
|
||||
* shiro登录认证
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = AuthenticationException.class)
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@ResponseBody
|
||||
public JSONObject handlerAuthenticationException(AuthenticationException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
return JsonResult.toJSONObj(ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = CompletionException.class)
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@ResponseBody
|
||||
@@ -69,6 +79,20 @@ public class GlobalExceptionHandler {
|
||||
return JsonResult.toJSONObj(errorMessages);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码异常
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = CaptchaException.class)
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@ResponseBody
|
||||
public JSONObject handlerCaptchaException(CaptchaException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
return JsonResult.toJSONObj(ex.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单检验(validator) 异常
|
||||
*
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package com.xwbing.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.xwbing.configuration.DispatcherServletConfig;
|
||||
import com.xwbing.constant.CommonConstant;
|
||||
import com.xwbing.util.CommonDataUtil;
|
||||
import com.xwbing.util.RestMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 说明: 登录拦截器
|
||||
* 项目名称: boot-module-demo
|
||||
* 创建时间: 2017/5/10 16:36
|
||||
* 作者: xiangwb
|
||||
*/
|
||||
public class LoginInterceptor extends HandlerInterceptorAdapter {
|
||||
private final Logger logger = LoggerFactory.getLogger(DispatcherServletConfig.class);
|
||||
private static final Set<String> set = new HashSet<>();//拦截器白名单
|
||||
|
||||
static {
|
||||
//映射到登录页面,不拦截
|
||||
set.add("/");
|
||||
//映射swagger文档
|
||||
set.add("/doc");
|
||||
//验证码
|
||||
set.add("/captcha");
|
||||
//swagger
|
||||
set.add("/v2/api-docs");
|
||||
set.add("/swagger-resources");
|
||||
set.add("/configuration/ui");
|
||||
set.add("/configuration/security");
|
||||
//德鲁伊监控
|
||||
set.add("/druid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String servletPath = request.getServletPath();
|
||||
if (!set.contains(servletPath) && !servletPath.contains("login") && !servletPath.contains("test")) {
|
||||
// HttpSession session = request.getSession();
|
||||
// if (session.getAttribute(CommonConstant.CURRENT_USER)!=null) {
|
||||
// return true;
|
||||
// }else {
|
||||
// return false;
|
||||
// }
|
||||
if (CommonDataUtil.getToken(CommonConstant.CURRENT_USER) != null) {
|
||||
return true;
|
||||
} else {
|
||||
logger.info("用户未登录");
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
RestMessage restMessage = new RestMessage();
|
||||
restMessage.setMessage("请先登录");
|
||||
outputStream.write(JSON.toJSONString(restMessage).getBytes("utf-8"));
|
||||
outputStream.close();
|
||||
//未登录,重定向到登录页面
|
||||
// response.sendRedirect("/login.html");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.xwbing.shiro;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
/**
|
||||
* 项目名称: boot-module-demo
|
||||
* 创建时间: 2018/3/29 15:28
|
||||
* 作者: xiangwb
|
||||
* 说明:
|
||||
*/
|
||||
public class FormAuthenticationCaptchaFilter extends FormAuthenticationFilter {
|
||||
public static final String DEFAULT_CAPTCHA_PARAM = "captcha_code";
|
||||
private String captchaParam = DEFAULT_CAPTCHA_PARAM;
|
||||
|
||||
public String getCaptchaParam() {
|
||||
return captchaParam;
|
||||
}
|
||||
|
||||
protected String getCaptcha(ServletRequest request) {
|
||||
return WebUtils.getCleanParam(request, getCaptchaParam());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
|
||||
String username = getUsername(request);
|
||||
String password = getPassword(request);
|
||||
String captcha = getCaptcha(request);
|
||||
boolean rememberMe = isRememberMe(request);
|
||||
String host = getHost(request);
|
||||
return new UsernamePasswordCaptchaToken(username, password.toCharArray(), rememberMe, host, captcha);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.xwbing.shiro;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
|
||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 项目名称: boot-module-demo
|
||||
* 创建时间: 2018/3/29 16:29
|
||||
* 作者: xiangwb
|
||||
* 说明:
|
||||
*/
|
||||
public class MySessionManager extends DefaultWebSessionManager {
|
||||
private static final String AUTHORIZATION = "Authorization";
|
||||
|
||||
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
|
||||
|
||||
public MySessionManager() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
|
||||
String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
|
||||
//如果请求头中有 Authorization 则其值为sessionId
|
||||
if (StringUtils.isNotEmpty(id)) {
|
||||
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
|
||||
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
|
||||
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
|
||||
return id;
|
||||
} else {
|
||||
//否则按默认规则从cookie取sessionId
|
||||
return super.getSessionId(request, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,9 @@ import com.xwbing.constant.CommonConstant;
|
||||
import com.xwbing.domain.entity.sys.SysAuthority;
|
||||
import com.xwbing.domain.entity.sys.SysRole;
|
||||
import com.xwbing.domain.entity.sys.SysUser;
|
||||
import com.xwbing.exception.BusinessException;
|
||||
import com.xwbing.service.sys.SysRoleService;
|
||||
import com.xwbing.service.sys.SysUserService;
|
||||
import com.xwbing.util.CommonDataUtil;
|
||||
import com.xwbing.util.captcha.CaptchaException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
@@ -72,7 +69,7 @@ public class MyShiroRealm extends AuthorizingRealm {
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证.登录
|
||||
* 登录.认证
|
||||
*
|
||||
* @param authenticationToken
|
||||
* @return
|
||||
@@ -81,22 +78,21 @@ public class MyShiroRealm extends AuthorizingRealm {
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
|
||||
UsernamePasswordCaptchaToken captchaToken = (UsernamePasswordCaptchaToken) authenticationToken;
|
||||
String captcha = captchaToken.getCaptcha();
|
||||
String imgCode = (String) SecurityUtils.getSubject().getSession().getAttribute(CommonConstant.KEY_CAPTCHA);
|
||||
// if (StringUtils.isEmpty(captcha) || !captcha.equalsIgnoreCase(imgCode)) {
|
||||
// throw new AuthenticationException("验证码错误");
|
||||
// }
|
||||
SysUser user = sysUserService.getByUserName(captchaToken.getUsername());
|
||||
if (user == null) {
|
||||
throw new BusinessException("账号错误");
|
||||
throw new AuthenticationException("账号或密码错误");
|
||||
}
|
||||
String sysPassWord = user.getPassword();
|
||||
String salt = user.getSalt();
|
||||
boolean flag = sysUserService.checkPassWord(String.valueOf(captchaToken.getPassword()), sysPassWord, salt);
|
||||
if (!flag) {
|
||||
throw new BusinessException("密码错误");
|
||||
throw new AuthenticationException("账号或密码错误");
|
||||
}
|
||||
String captcha = captchaToken.getCaptcha();
|
||||
String imgCode = (String) CommonDataUtil.getToken(CommonConstant.KEY_CAPTCHA);
|
||||
if (StringUtils.isEmpty(captcha) || !captcha.equalsIgnoreCase(imgCode)) {
|
||||
throw new CaptchaException("验证码错误");
|
||||
}
|
||||
return new SimpleAuthenticationInfo(user, sysPassWord,
|
||||
ByteSource.Util.bytes(salt), getName());
|
||||
return new SimpleAuthenticationInfo(user, sysPassWord, ByteSource.Util.bytes(salt), getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.xwbing.shiro;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -16,37 +18,43 @@ import java.util.Map;
|
||||
* 说明: anon,authc
|
||||
*/
|
||||
@Configuration
|
||||
@PropertySource("classpath:shiro.properties")
|
||||
public class ShiroConfig {
|
||||
@Value("${rememberMeCookieMaxAge}")
|
||||
private Integer rememberMeCookieMaxAge;
|
||||
@Value("${globalSessionTimeout}")
|
||||
private Long globalSessionTimeout;
|
||||
@Value("${sessionValidationInterval}")
|
||||
private String sessionValidationInterval;
|
||||
@Value("${sessionsCacheName}")
|
||||
private String sessionsCacheName;
|
||||
@Value("${sessionIdCookieName}")
|
||||
private String sessionIdCookieName;
|
||||
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
|
||||
public ShiroFilterFactoryBean shirFilter() {
|
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
||||
//配置登录的url和登录成功的url
|
||||
shiroFilterFactoryBean.setLoginUrl("/login");
|
||||
shiroFilterFactoryBean.setSuccessUrl("/index");
|
||||
// 未授权界面;
|
||||
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager());
|
||||
//配置访问权限
|
||||
Map<String, String> chains = new LinkedHashMap<>();
|
||||
// 配置不会被拦截的链接 顺序判断
|
||||
chains.put("/favicon.ico", "anon");
|
||||
chains.put("/static/**", "anon");
|
||||
//映射到登录页面,不拦截
|
||||
chains.put("/","anon");
|
||||
//映射swagger文档
|
||||
chains.put("/doc","anon");
|
||||
//验证码
|
||||
chains.put("/captcha","anon");
|
||||
//swagger
|
||||
chains.put("/v2/api-docs","anon");
|
||||
chains.put("/swagger-resources","anon");
|
||||
chains.put("/configuration/ui","anon");
|
||||
chains.put("/configuration/security","anon");
|
||||
//德鲁伊监控
|
||||
chains.put("/druid","anon");
|
||||
chains.put("/**", "authc");
|
||||
//配置登录的url和登录成功的url
|
||||
shiroFilterFactoryBean.setLoginUrl("/user/login");
|
||||
// shiroFilterFactoryBean.setSuccessUrl("/index");
|
||||
// 未授权界面;
|
||||
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
|
||||
// chains.put("/favicon.ico", "anon");
|
||||
// chains.put("/static/**", "anon");
|
||||
// chains.put("/", "anon");
|
||||
// chains.put("/doc", "anon");
|
||||
// chains.put("/captcha", "anon");
|
||||
// chains.put("/v2/api-docs", "anon");
|
||||
// chains.put("/swagger-resources", "anon");
|
||||
// chains.put("/configuration/ui", "anon");
|
||||
// chains.put("/configuration/security", "anon");
|
||||
// chains.put("/druid", "anon");
|
||||
// chains.put("/**", "authc");
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(chains);
|
||||
System.out.println("Shiro拦截器工厂类注入成功");
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ public class UsernamePasswordCaptchaToken extends UsernamePasswordToken {
|
||||
private static final long serialVersionUID = 6059396037971862504L;
|
||||
private String captcha;
|
||||
|
||||
public UsernamePasswordCaptchaToken() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
public UsernamePasswordCaptchaToken(String username, char[] password, boolean rememberMe, String host, String captcha) {
|
||||
super(username, password, rememberMe, host);
|
||||
this.captcha = captcha;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
### s
|
||||
rememberMeCookieMaxAge=604800
|
||||
globalSessionTimeout=1800000
|
||||
sessionValidationInterval=60000
|
||||
sessionsCacheName=shiro-activeSessionCache
|
||||
sessionIdCookieName=drore.session.ywjpjScenic.id
|
||||
path=/
|
||||
Reference in New Issue
Block a user