由于项目框架古老spring3.0 spring security2.0.4,但功能齐全,所以个人想要升级各个jar包版本,以减少不必要的已知bug
目标更换为spring security4.2 spring data换为最新
问题1:spring版本不匹配,jar包冲突
这个是最好解决的,先把spring security做最基础配置,换几个理论上兼容的spring版本试试就行,最终选定spring 4.3.18,
较为稳定且各方面都满足需求,耗时10分钟
问题2:项目需实现3种角色4种版本登录,网上相关文章不多且大多是基本配置,无法达到项目需要
只能自己一步一步摸索,总共写了29个demo,各种冲突bug应有尽有,网上的各种配置排除重复的几乎也试了个遍,要么用不上要么功能不全,最终把多篇文章终于组合完成,自定义了loginFilter 以及权限filter,能够实现各个权限的随意配置,因项目需要未做分组管理角色,角色与各权限几乎是一对一
自定义了各个链接地址以及跳转url
package com.www.common.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
import java.util.Iterator;
/**
* 访问决策器
* 决定某个用户具有的角色
* 是否有足够的权限去访问某个资源
* 在这种方法中,需要与configAttributes比较验证
* 1、一个对象是一个URL,一个过滤器被这个URL找到权限配置,并通过这里
* 2、如果没有匹配相应的认证,AccessDeniedException
* @author
*/
public class DecisionManager implements AccessDecisionManager {
private Logger log= LoggerFactory.getLogger(DecisionManager.class);
/**
* 在这个类中,最重要的是decide方法,如果不存在对该资源的定义,直接放行
* 否则,如果找到正确的角色,即认为拥有权限,并放行,
* 否则throw new AccessDeniedException("no right");
* 这样,就会进入上面提到的/accessDenied.jsp页面。
* @param authentication :当前用户所有的角色
* @param object :当前请求的URL
* @param configAttributes :当前URL所需要的角色
*/
@Override
public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
// 资源所需的角色列表,如果角色列表为空,则放行!继续下一个拦截器。
if (configAttributes == null) {
return;
}
log.info("%%%%%authentication :"+authentication.toString());
log.info("&&&&&configAttributes :"+configAttributes.toString());
// 即将访问的资源URL,如 : /admin.jsp
log.info("URL :"+object);
// 遍历所需的角色集合
Iterator ite = configAttributes.iterator();
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
// 该资源所需要的角色
String needRole = ca.getAttribute();
// authentication.getAuthorities()获取用户所拥有的角色列表,如:OLE_DEFULT
for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
// 将资源所需要的角色与用户拥有的角色比较
if (needRole.equals(grantedAuthority.getAuthority())) {
// 角色相同,直接放行
return;
}
}
}
// 否则,提示没有权限访问该资源
throw new AccessDeniedException("no right");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class> clazz) {
return true;
}
}
package com.www.common.security;
import com.www.common.enums.Constant;
import com.www.common.enums.RoleType;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.*;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.RedirectUrlBuilder;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 访问资源无权限时访问
* @Author: zhouchaoxi
* @Date: Created in 2018/7/7 0:13
* @Modified By:
*/
public class LoginEntryPoint implements AuthenticationEntryPoint,InitializingBean {
private PortMapper portMapper = new PortMapperImpl();
private PortResolver portResolver = new PortResolverImpl();
private String loginFormUrl;
private boolean forceHttps = false;
private boolean useForward = false;
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
public LoginEntryPoint(String loginFormUrl) {
Assert.notNull(loginFormUrl, "loginFormUrl cannot be null");
this.loginFormUrl = loginFormUrl;
}
/**
* Performs the redirect (or forward) to the login form URL.
*/
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
String redirectUrl = null;
String returnUrl = buildHttpReturnUrlForRequest(request);
System.out.println("========"+returnUrl+"========");
if (returnUrl.contains("/admin/")){
request.getSession().setAttribute(Constant.LOGIN_ROLE, RoleType.ADMIN());
this.loginFormUrl="/admin/login.do";
}else{
request.getSession().setAttribute(Constant.LOGIN_ROLE, RoleType.USER());
}
if (useForward) {
if (forceHttps && "http".equals(request.getScheme())) {
redirectUrl = buildHttpsRedirectUrlForRequest(request);
}
if (redirectUrl == null) {
String loginForm = determineUrlToUseForThisRequest(request, response, authException);
RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);
dispatcher.forward(request, response);
return;
}
} else {
redirectUrl = buildRedirectUrlToLoginPage(request, response, authException);
}
redirectStrategy.sendRedirect(request, response, redirectUrl);
}
protected String buildHttpReturnUrlForRequest(HttpServletRequest request) throws IOException, ServletException {
RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
urlBuilder.setScheme("http");
urlBuilder.setServerName(request.getServerName());
urlBuilder.setPort(request.getServerPort());
urlBuilder.setContextPath(request.getContextPath());
urlBuilder.setServletPath(request.getServletPath());
urlBuilder.setPathInfo(request.getPathInfo());
urlBuilder.setQuery(request.getQueryString());
return urlBuilder.getUrl();
}
public void afterPropertiesSet() throws Exception {
Assert.isTrue(StringUtils.hasText(loginFormUrl) && UrlUtils.isValidRedirectUrl(loginFormUrl),
"loginFormUrl must be specified and must be a valid redirect URL");
if (useForward && UrlUtils.isAbsoluteUrl(loginFormUrl)) {
throw new IllegalArgumentException("useForward must be false if using an absolute loginFormURL");
}
Assert.notNull(portMapper, "portMapper must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
}
/**
* Allows subclasses to modify the login form URL that should be applicable for a
* given request.
*
* @param request the request
* @param response the response
* @param exception the exception
* @return the URL (cannot be null or empty; defaults to {@link #getLoginFormUrl()})
*/
protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
return getLoginFormUrl();
}
protected String buildRedirectUrlToLoginPage(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
String loginForm = determineUrlToUseForThisRequest(request, response, authException);
if (UrlUtils.isAbsoluteUrl(loginForm)) {
return loginForm;
}
int serverPort = portResolver.getServerPort(request);
String scheme = request.getScheme();
RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
urlBuilder.setScheme(scheme);
urlBuilder.setServerName(request.getServerName());
urlBuilder.setPort(serverPort);
urlBuilder.setContextPath(request.getContextPath());
urlBuilder.setPathInfo(loginForm);
if (forceHttps && "http".equals(scheme)) {
Integer httpsPort = portMapper.lookupHttpsPort(Integer.valueOf(serverPort));
if (httpsPort != null) {
// Overwrite scheme and port in the redirect URL
urlBuilder.setScheme("https");
urlBuilder.setPort(httpsPort.intValue());
}
else {
}
}
return urlBuilder.getUrl();
}
/**
* Builds a URL to redirect the supplied request to HTTPS. Used to redirect the
* current request to HTTPS, before doing a forward to the login page.
*/
protected String buildHttpsRedirectUrlForRequest(HttpServletRequest request) throws IOException, ServletException {
int serverPort = portResolver.getServerPort(request);
Integer httpsPort = portMapper.lookupHttpsPort(Integer.valueOf(serverPort));
if (httpsPort != null) {
RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
urlBuilder.setScheme("https");
urlBuilder.setServerName(request.getServerName());
urlBuilder.setPort(httpsPort.intValue());
urlBuilder.setContextPath(request.getContextPath());
urlBuilder.setServletPath(request.getServletPath());
urlBuilder.setPathInfo(request.getPathInfo());
urlBuilder.setQuery(request.getQueryString());
return urlBuilder.getUrl();
}
return null;
}
/**
* Set to true to force login form access to be via https. If this value is true (the
* default is false), and the incoming request for the protected resource which
* triggered the interceptor was not already https
, then the client will
* first be redirected to an https URL, even if serverSideRedirect is set to
* true.
*/
public void setForceHttps(boolean forceHttps) {
this.forceHttps = forceHttps;
}
protected boolean isForceHttps() {
return forceHttps;
}
public String getLoginFormUrl() {
return loginFormUrl;
}
public void setPortMapper(PortMapper portMapper) {
Assert.notNull(portMapper, "portMapper cannot be null");
this.portMapper = portMapper;
}
protected PortMapper getPortMapper() {
return portMapper;
}
public void setPortResolver(PortResolver portResolver) {
Assert.notNull(portResolver, "portResolver cannot be null");
this.portResolver = portResolver;
}
protected PortResolver getPortResolver() {
return portResolver;
}
/**
* Tells if we are to do a forward to the {@code loginFormUrl} using the
* {@code RequestDispatcher}, instead of a 302 redirect.
*
* @param useForward true if a forward to the login page should be used. Must be false
* (the default) if {@code loginFormUrl} is set to an absolute value.
*/
public void setUseForward(boolean useForward) {
this.useForward = useForward;
}
protected boolean isUseForward() {
return useForward;
}
}
package com.www.common.security;
import com.www.common.enums.Constant;
import com.www.common.utils.Const;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @描述:
* @作者: zhouChaoXi
* @时间: 2018/7/3 21:20
*/
public class LoginFromFilter extends UsernamePasswordAuthenticationFilter{
public static final String SPRING_SECURITY_FORM_VALID_CODE = "code";
private String codeParameter = SPRING_SECURITY_FORM_VALID_CODE;
public LoginFromFilter() {
super();
}
/**
* 如果是通过页面进来验证码效验
* 非页面进入不效验
* 并拼接用户名和登录角色
* @Author: zhouchaoxi
* @Date: Created in 2018/8/4 17:44
* @Modified By:
*/
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String code = (String)request.getSession().getAttribute(Constant.CODE);
String inputCode = obtainValidCode(request);
String login_role=request.getParameter(Constant.LOGIN_ROLE);
request.getSession().setAttribute(Constant.LOGIN_ROLE,login_role);
String username=obtainUsername(request);
String password=obtainPassword(request);
if (username == null)username = "";
if (password == null)password = "";
username=username+"__"+login_role;
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
setDetails(request, authRequest);
if (code==null){
return super.getAuthenticationManager().authenticate(authRequest);
}else if(code.toUpperCase().equals(inputCode.toUpperCase())){
return super.getAuthenticationManager().authenticate(authRequest);
}else{
throw new AuthenticationServiceException("验证码输入错误");
}
}
protected String obtainValidCode(HttpServletRequest request) {
return request.getParameter(codeParameter);
}
public String getCodeParameter() {
return codeParameter;
}
public void setCodeParameter(String codeParameter) {
Assert.hasText(codeParameter, "Valid code parameter must not be empty or null");
this.codeParameter = codeParameter;
}
}
package com.www.common.security;
import com.www.common.enums.RoleType;
import com.www.common.pojo.User;
import com.www.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
/**
* 从数据库中读入用户的密码
* 角色信息,是否锁定,账号是否过期等
* @author
*/
public class MyUserDetailService implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String[] usernameList=username.split("__");
String userName="";
String login_role= RoleType.USER();
if (usernameList.length>1){
for(int i=0;i auths = new ArrayList();
// String roles=user.getUserRole();
// if (!CommUtil.isNull(roles)){
// String[] role=roles.split(",");
// for (String auth:role){
// auths.add(new SimpleGrantedAuthority(auth));
// }
// }
// User userDetails = new User(username, user.getPassword(), true, true, true, true, auths);
return user;
}
throw new UsernameNotFoundException("UserName " + username + " not found");
}
}
package com.www.common.security;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import javax.servlet.*;
import java.io.IOException;
/**
* 拦截器核心
*/
public class SecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Override
public void init(FilterConfig filterConfig){
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
/**
* 最核心的代码就是@link InterceptorStatusToken token = super.beforeInvocation(fi);
* 它会调用我们定义的MyInvocationSecurityMetadataSource.getAttributes方法和MyAccessDecisionManager.decide方法
* 这一句,即在执行doFilter之前,进行权限的检查,而具体的实现已经交给@link DecisionManager 了
*/
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
//继续走下一个拦截器,也就是org.springframework.security.web.access.intercept.FilterSecurityInterceptor
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
@Override
public Class> getSecureObjectClass() {
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
}
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
}
}
package com.www.common.security;
import com.www.service.ResService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 定义某一资源可以被哪些角色访问
* @author
*/
public class SecurityMetadataSource implements FilterInvocationSecurityMetadataSource,InitializingBean{
private Logger log= LoggerFactory.getLogger(SecurityMetadataSource.class);
private static HashMap> allResource;
@Autowired
private ResService resService;
@Override
public Collection getAttributes(Object object) throws IllegalArgumentException {
FilterInvocation fi = (FilterInvocation) object;
// 访问的路径
String requestUrl = fi.getRequest().getRequestURI();
List attributes = new ArrayList();
// 所有URL对应的角色,应用启动就存放到静态资源里,得到的结果是:不同的URL下,包含的多个角色
HashMap> resRoles = allResource;
if(!resRoles.isEmpty()){
for (Map.Entry> ent : resRoles.entrySet()) {
// 需要验证的url
String url = ent.getKey();
List roles = ent.getValue();
//根据业务写自己的匹配逻辑
if(url!=null&&requestUrl.contains(url)){
attributes=roles;
}
}
}
log.debug("【"+fi.getRequest().getRequestURI()+"】 roles: "+attributes);
return attributes;
}
@Override
public Collection getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
@Override
public void afterPropertiesSet() throws Exception {
loadResourceDefine();
}
private void loadResourceDefine() {
if(allResource == null) {
allResource = new HashMap<>();
}else{
allResource.clear();
}
Map> resourceRoleMap = resService.getAllResourceRole();
for (Map.Entry> entry : resourceRoleMap.entrySet()) {
// 需要权限的url
String url = entry.getKey();
// 可以访问此url的角色
List values = entry.getValue();
List configAttributes = new ArrayList();
for(String role : values){
configAttributes.add(new SecurityConfig(role));
}
allResource.put(url, configAttributes);
}
}
}
package com.www.common.security;
import com.www.common.pojo.User;
import com.www.common.utils.CommUtil;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class SecurityUserHolder {
public static User getCurrentUser() {
if (SecurityContextHolder.getContext().getAuthentication() != null) {
if ((SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof User)) {
return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
}
User user = null;
if (RequestContextHolder.getRequestAttributes() != null) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession(false);
if (session != null)
user = session.getAttribute("user") != null ? (User) session.getAttribute("user") : null;
}
return user;
}
}
package com.www.common.security;
import com.www.common.enums.Constant;
import com.www.common.enums.RoleType;
import com.www.common.pojo.UserConfig;
import com.www.common.utils.CommUtil;
import com.www.service.UserConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* 权限验证成功
* @author
*/
public class SuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private UserConfigService userConfigService;
private Logger log= LoggerFactory.getLogger(SuccessHandler.class);
/**
*登录成功后的操作
* @Author: zhouchaoxi
* @Date: Created in 2018/8/4 18:24
* @Modified By:
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse rep, Authentication auths) throws IOException, ServletException {
System.out.println("=========================登录成功==============================");
String s = "\n"+
" _ooOoo_"+"\n"+
" o8888888o"+"\n"+
" 88\" . \"88"+"\n"+
" (| -_- |)"+"\n"+
" O\\ = /O"+"\n"+
" ____/`---'\\____"+"\n"+
" . ' \\| |// `."+"\n"+
" / \\\\||| : |||// \\"+"\n"+
" / _||||| -:- |||||- \\"+"\n"+
" | | | \\\\\\ - /// | |"+"\n"+
" | \\_| ''\\---/'' | |"+"\n"+
" \\ .-\\__ `-` ___/-. /"+"\n"+
" ___\"`. .' /--.--\\ `. . __"+"\n"+
" .\"\" '< `.___\\_<|>_/___.' >'\"\"."+"\n"+
" | | : `- \\`.;`\\ _ /`;.`/ - ` : | |"+"\n"+
" \\ \\ `-. \\_ __\\ /__ _/ .-` / /"+"\n"+
" ======`-.____`-.___\\_____/___.-`____.-'======";
log.info(s);
clearAuthenticationAttributes(req);
String targetUrl = "/index.do";
// 根据登录角色不同跳转不同页面
String role= (String) req.getSession().getAttribute(Constant.LOGIN_ROLE);
req.getSession().removeAttribute(Constant.CODE);
if (RoleType.ADMIN().equals(role)){
targetUrl="/admin/index.do";
}else if (RoleType.SELLER().equals(role)){
targetUrl="/seller/index.do";
}
UserConfig config=userConfigService.getObjectById(SecurityUserHolder.getCurrentUser().getId());
config.setLoginCount(config.getLoginCount()+1);
config.setLoginDate(new Date());
config.setLoginIp(CommUtil.getIpAddr(req));
userConfigService.save(config);
getRedirectStrategy().sendRedirect(req, rep, targetUrl);
}
}
spring的配置相对简单就不赘述,都是基本配置,后面附完整的xml,耗时3小时
问题3:配置完自定义过后配置maxsession失效,单点登录功能丧失,网上找了n篇文章,n套美其名曰完整项目的配置都不生效
进源码debug登录成功始终不进registernewsession方法,又去网上找了半天也没有合适的,于是决定自己研究,把security所可能用到的方法打上debug,登录成功一步一步过,查看官方文档说明找到了问题所在,SessionAuthenticationStrategy:该接口中存在onAuthentication方法用于对新登录用户进行session相关的校验。查看UsernamePasswordAuthenticationFilter及其父类代码,可以发现在doFilter中存在sessionStrategy.onAuthentication(authResult, request, response);方法
但UsernamePasswordAuthenticationFilter中的sessionStrategy对象默认为NullAuthenticatedSessionStrategy,即不对session进行相关验证。
去掉通用的maxsession配置,加入sessionfilter,注入sessionStrategy
测试2个浏览器登录,OK,我去一个简单的配置找遍了网上也没有。。。。
这就郁闷了,所以才有了本文
整理完过后的完整xml如下,因为不需要记住密码功能,所以本项目没有加入,需要加入配置一个remberme就好了,那个相对简单
4.0.0
SSH
SSH
0.0.1-SNAPSHOT
war
SSH
UTF-8
4.3.18.RELEASE
5.0.12.Final
javax
javaee-api
7.0
provided
org.springframework
spring-beans
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-context-support
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-webmvc
${spring.version}
com.alibaba
druid
1.1.10
net.sf.ehcache
ehcache-core
2.6.11
com.fasterxml.jackson.core
jackson-databind
2.9.5
com.google.code.gson
gson
2.8.5
org.aspectj
aspectjrt
1.8.5
org.aspectj
aspectjweaver
1.8.5
org.hibernate
hibernate-core
${hibernate.version}
org.hibernate
hibernate-entitymanager
${hibernate.version}
org.hibernate
hibernate-ehcache
${hibernate.version}
org.springframework.data
spring-data-jpa
1.10.11.RELEASE
mysql
mysql-connector-java
5.1.46
com.alipay.sdk
alipay-sdk-java
3.3.4.ALL
com.github.binarywang
weixin-java-pay
3.1.1.BETA
org.apache.poi
poi
3.6
org.slf4j
slf4j-api
1.7.25
org.slf4j
slf4j-simple
1.7.25
org.apache.logging.log4j
log4j-core
2.10.0
org.apache.logging.log4j
log4j-jcl
2.10.0
commons-lang
commons-lang
2.6
commons-io
commons-io
2.6
commons-codec
commons-codec
1.11
commons-beanutils
commons-beanutils
1.9.3
commons-fileupload
commons-fileupload
1.3.3
jdom
jdom
1.1
dom4j
dom4j
1.6.1
org.quartz-scheduler
quartz
2.3.0
org.apache.velocity
velocity
1.7
org.apache.velocity
velocity-tools
2.0
org.springframework.security
spring-security-core
4.2.7.RELEASE
org.springframework.security
spring-security-config
4.2.7.RELEASE
org.springframework.security
spring-security-web
4.2.7.RELEASE
com.upyun
java-sdk
4.0.1
com.google.zxing
core
3.3.3
com.google.zxing
javase
3.3.3
redis.clients
jedis
2.9.0
org.apache.httpcomponents
httpclient
4.5.6
org.apache.httpcomponents
httpcore
4.4.10
org.apache.httpcomponents
httpmime
4.5.6
commons-httpclient
commons-httpclient
3.1
maven-compiler-plugin
2.3.2
1.7
maven-war-plugin
2.2
false
com.www.common.utils.ImprovedNamingStrategy
update
true
org.hibernate.dialect.MySQLDialect
true
org.hibernate.cache.ehcache.EhCacheRegionFactory
true
D:/logs/
SSSlog
至此项目整合完成
完整项目下载链接https://download.csdn.net/download/qq_40615366/10589664