From 2f52e8c752122625f189ae7657e621db0d6d253c Mon Sep 17 00:00:00 2001 From: 李宇 <986321569@qq.com> Date: 星期四, 28 一月 2021 09:39:19 +0800 Subject: [PATCH] 修改安全测评内容 --- src/main/java/com/nanometer/smartlab/email/EmailSendSchedule.java | 3 src/main/webapp/WEB-INF/spring-shiro.xml | 47 ++ src/main/java/com/nanometer/smartlab/api/schedule/ReagentSyncSchedule.java | 6 src/main/java/com/nanometer/smartlab/realm/RetryLimitCredentialsMatcher.java | 87 ++++ src/main/java/com/nanometer/smartlab/service/OpeOrderServiceImpl.java | 4 src/main/java/com/nanometer/smartlab/service/InterfaceServiceImpl.java | 3 src/main/java/com/nanometer/smartlab/service/SysControllerServiceImpl.java | 8 src/main/webapp/user_mng.xhtml | 3 src/main/java/com/nanometer/smartlab/api/schedule/UserPointSchedule.java | 2 src/main/java/org/apache/shiro/web/filter/InvalidRequestFilter.java | 88 ++-- src/main/java/com/nanometer/smartlab/entity/OpeApply.java | 9 src/main/java/com/nanometer/smartlab/realm/ShiroDbRealm.java | 109 +++++ src/main/java/org/springframework/web/filter/DelegatingFilterProxy.java | 409 +++++++++++++++++++++ src/main/java/com/nanometer/smartlab/api/ApiAction.java | 26 src/main/webapp/WEB-INF/spring-mvc.xml | 7 src/main/webapp/index.xhtml | 12 src/main/java/com/nanometer/smartlab/realm/ShiroSpringCache.java | 113 +++++ src/main/java/com/nanometer/smartlab/service/OpeReagentStatusServiceImpl.java | 4 src/main/java/com/nanometer/smartlab/service/OpeApplyServiceImpl.java | 4 src/main/java/com/nanometer/smartlab/realm/ShiroSpringCacheManager.java | 63 +++ src/main/java/com/nanometer/smartlab/controller/LoginController.java | 4 src/main/java/com/nanometer/smartlab/util/Validator.java | 48 ++ src/main/java/com/nanometer/smartlab/service/OpeUseFlowServiceImpl.java | 10 src/main/java/com/nanometer/smartlab/service/OpeWarehouseReserveServiceImpl.java | 19 src/main/webapp/WEB-INF/test/test.properties | 3 src/main/webapp/login.xhtml | 8 26 files changed, 990 insertions(+), 109 deletions(-) diff --git a/src/main/java/com/nanometer/smartlab/api/ApiAction.java b/src/main/java/com/nanometer/smartlab/api/ApiAction.java index 4ce057e..895fbec 100644 --- a/src/main/java/com/nanometer/smartlab/api/ApiAction.java +++ b/src/main/java/com/nanometer/smartlab/api/ApiAction.java @@ -28,6 +28,7 @@ import org.apache.shiro.subject.Subject; import org.primefaces.context.RequestContext; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @@ -49,46 +50,55 @@ public class ApiAction extends BaseAction { private static Logger logger = Logger.getLogger(ApiAction.class); - + @Lazy @Resource private SysUserService sysUserService; + @Lazy @Resource private OpeReagentStatusService opeReagentStatusService; - @Resource - private SysReagentService sysReagentService; + @Lazy @Resource private SysWarehouseContainerService sysWarehouseContainerService; + @Lazy @Resource private SysLaboratoryContainerService sysLaboratoryContainerService; + @Lazy @Resource private BaseMetaService baseMetaService; + @Lazy @Resource private InterfaceService interfaceService; + @Lazy @Resource private SysWarehouseService sysWarehouseService; - - @Resource - private SysWarningService sysWarningService; - + @Lazy @Resource private TempSensorsService tempSensorsService; - + @Lazy @Resource private SysFileService sysFileService; + @Lazy @Resource private SysLaboratoryContainerDao sysLaboratoryContainerDao; + @Lazy @Resource private SysWarehouseContainerDao sysWarehouseContainerDao; + @Lazy @Resource private DangerousEncodeService dangerousEncodeService; + @Lazy @Resource private EncodeReplaceDictService encodeReplaceDictService; + @Lazy @Resource private SysLaboratoryService sysLaboratoryService; + @Lazy @Resource private HazardousWasteService hazardousWasteService; + @Lazy @Resource private OpeLaboratoryReserveService opeLaboratoryReserveService; + @Lazy @Resource private OpeUseFlowService opeUseFlowService; @Value("${institute.url}") diff --git a/src/main/java/com/nanometer/smartlab/api/schedule/ReagentSyncSchedule.java b/src/main/java/com/nanometer/smartlab/api/schedule/ReagentSyncSchedule.java index ac00ccf..347d7e2 100644 --- a/src/main/java/com/nanometer/smartlab/api/schedule/ReagentSyncSchedule.java +++ b/src/main/java/com/nanometer/smartlab/api/schedule/ReagentSyncSchedule.java @@ -7,6 +7,7 @@ import org.apache.commons.lang.time.DateFormatUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -40,14 +41,19 @@ private String reagentStatusUrl; @Value("${sensors.url}") private String reagentSensorsUrl; + @Lazy @Resource private BaseMetaService baseMetaService; + @Lazy @Resource private OpeReagentStatusService reagentStatusService; + @Lazy @Resource private OpeUseFlowService opeUseFlowService; + @Lazy @Resource private SysContainerSensorsService sysContainerSensorsService; + @Lazy @Resource private SysUserService sysUserService; diff --git a/src/main/java/com/nanometer/smartlab/api/schedule/UserPointSchedule.java b/src/main/java/com/nanometer/smartlab/api/schedule/UserPointSchedule.java index e4f60c3..de15a9d 100644 --- a/src/main/java/com/nanometer/smartlab/api/schedule/UserPointSchedule.java +++ b/src/main/java/com/nanometer/smartlab/api/schedule/UserPointSchedule.java @@ -3,6 +3,7 @@ import com.nanometer.smartlab.service.SysUserService; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -11,6 +12,7 @@ @Component public class UserPointSchedule { private static Logger logger = Logger.getLogger(UserPointSchedule.class); + @Lazy @Autowired private SysUserService sysUserService; diff --git a/src/main/java/com/nanometer/smartlab/controller/LoginController.java b/src/main/java/com/nanometer/smartlab/controller/LoginController.java index 5b8f383..3ac1190 100644 --- a/src/main/java/com/nanometer/smartlab/controller/LoginController.java +++ b/src/main/java/com/nanometer/smartlab/controller/LoginController.java @@ -6,6 +6,7 @@ import com.nanometer.smartlab.util.FacesUtils; import org.apache.log4j.Logger; import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; @@ -42,6 +43,9 @@ } catch (UnknownAccountException e) { FacesUtils.warn("用户名不存在"); return null; + } catch (ExcessiveAttemptsException e) { + FacesUtils.warn("登陆失败,密码连续输入错误超过5次,锁定5分钟!"); + return null; } catch (Exception e) { logger.error("登陆失败", e); } diff --git a/src/main/java/com/nanometer/smartlab/email/EmailSendSchedule.java b/src/main/java/com/nanometer/smartlab/email/EmailSendSchedule.java index 3ae54f2..a88d64c 100644 --- a/src/main/java/com/nanometer/smartlab/email/EmailSendSchedule.java +++ b/src/main/java/com/nanometer/smartlab/email/EmailSendSchedule.java @@ -6,6 +6,7 @@ import com.nanometer.smartlab.service.*; import com.nanometer.smartlab.util.EmailSend; import org.apache.log4j.Logger; +import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -17,7 +18,7 @@ */ @Component public class EmailSendSchedule { - + @Lazy @Resource private OpeOrderService opeOrderService; diff --git a/src/main/java/com/nanometer/smartlab/entity/OpeApply.java b/src/main/java/com/nanometer/smartlab/entity/OpeApply.java index e2eba2e..ad696f2 100644 --- a/src/main/java/com/nanometer/smartlab/entity/OpeApply.java +++ b/src/main/java/com/nanometer/smartlab/entity/OpeApply.java @@ -2,6 +2,7 @@ import com.nanometer.smartlab.entity.enumtype.ApplyStatus; import com.nanometer.smartlab.entity.enumtype.ValidFlag; +import com.nanometer.smartlab.util.Validator; import java.io.Serializable; import java.math.BigDecimal; @@ -132,7 +133,7 @@ } public void setApplyGoal(String applyGoal) { - this.applyGoal = applyGoal; + this.applyGoal = Validator.filter(applyGoal); } public String getId() { @@ -156,7 +157,7 @@ } public void setNum(Integer num) { - this.num = num; + this.num = Integer.parseInt(Validator.filter(num.toString())); } public String getApplyUserId() { @@ -172,7 +173,7 @@ } public void setObjective(String objective) { - this.objective = objective; + this.objective = Validator.filter(objective); } public Timestamp getCreateTime() { @@ -210,7 +211,7 @@ this.beforeApproveUserId=beforeApproveUserId; } public void setApproveUserId(String approveUserId) { - this.approveUserId = approveUserId; + this.approveUserId = Validator.filter(approveUserId); } public String getMemo() { diff --git a/src/main/java/com/nanometer/smartlab/realm/RetryLimitCredentialsMatcher.java b/src/main/java/com/nanometer/smartlab/realm/RetryLimitCredentialsMatcher.java new file mode 100644 index 0000000..7f5739c --- /dev/null +++ b/src/main/java/com/nanometer/smartlab/realm/RetryLimitCredentialsMatcher.java @@ -0,0 +1,87 @@ +/** + * The MIT License (MIT) + * Copyright (c) 2016 Dreamlu (596392912@qq.com). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.nanometer.smartlab.realm; + +import org.apache.log4j.Logger; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.ExcessiveAttemptsException; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheManager; +import org.springframework.beans.factory.InitializingBean; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 输错5次密码锁定半小时,ehcache.xml配置 + * + */ +public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher implements InitializingBean { + private final static Logger logger = Logger.getLogger(RetryLimitCredentialsMatcher.class); + private final static String DEFAULT_CHACHE_NAME = "retryLimitCache"; + + private final CacheManager cacheManager; + private String retryLimitCacheName; + private Cache<String, AtomicInteger> passwordRetryCache; + + public RetryLimitCredentialsMatcher(CacheManager cacheManager) { + this.cacheManager = cacheManager; + this.retryLimitCacheName = DEFAULT_CHACHE_NAME; + } + + public String getRetryLimitCacheName() { + return retryLimitCacheName; + } + public void setRetryLimitCacheName(String retryLimitCacheName) { + this.retryLimitCacheName = retryLimitCacheName; + } + + @Override + public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) { + String username = (String) authcToken.getPrincipal(); + //retry count + 1 + AtomicInteger retryCount = passwordRetryCache.get(username); + if(retryCount == null) { + retryCount = new AtomicInteger(0); + passwordRetryCache.put(username, retryCount); + } + if(retryCount.incrementAndGet() > 5) { + //if retry count > 5 throw + logger.warn("username: " + username + " tried to login more than 5 times in period"); +// FacesUtils.warn("用户名: " + username + " 密码连续输入错误超过5次,锁定5分钟!"); + throw new ExcessiveAttemptsException("用户名: " + username + " 密码连续输入错误超过5次,锁定5分钟!"); + } + + boolean matches = super.doCredentialsMatch(authcToken, info); + if(matches) { + //clear retry data + passwordRetryCache.remove(username); + } + return matches; + } + + @Override + public void afterPropertiesSet() throws Exception { + this.passwordRetryCache = cacheManager.getCache(retryLimitCacheName); + } +} diff --git a/src/main/java/com/nanometer/smartlab/realm/ShiroDbRealm.java b/src/main/java/com/nanometer/smartlab/realm/ShiroDbRealm.java new file mode 100644 index 0000000..83ca292 --- /dev/null +++ b/src/main/java/com/nanometer/smartlab/realm/ShiroDbRealm.java @@ -0,0 +1,109 @@ +package com.nanometer.smartlab.realm; + +import com.nanometer.smartlab.entity.BaseRolePage; +import com.nanometer.smartlab.entity.SysUser; +import com.nanometer.smartlab.service.BaseRolePageService; +import com.nanometer.smartlab.service.SysUserService; +import com.nanometer.smartlab.util.Constants; +import org.apache.log4j.Logger; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheManager; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.SimplePrincipalCollection; +import org.apache.shiro.subject.Subject; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; + +/** + * @description:shiro权限认证 + * @author:zhixuan.wang + * @date:2015/10/1 14:51 + */ +public class ShiroDbRealm extends AuthorizingRealm { + private static Logger LOGGER = Logger.getLogger(ShiroDbRealm.class); + + @Resource + private SysUserService sysUserService; + @Resource + private BaseRolePageService baseRolePageService; + + public ShiroDbRealm(CacheManager cacheManager, CredentialsMatcher matcher) { + super(cacheManager, matcher); + } + + /** + * Shiro登录认证(原理:用户提交 用户名和密码 --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 ) + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; + final String account = String.valueOf(usernamePasswordToken.getUsername()); + SysUser user = this.sysUserService.getSysUserByAccount(account); + + if (user == null) { + throw new UnknownAccountException(); + } + + AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getAccount(), user.getPassword(), getName()); + + return authenticationInfo; + } + + /** + * Shiro权限认证 + */ + @Override + protected AuthorizationInfo doGetAuthorizationInfo( + PrincipalCollection principals) { + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + + String account = (String) super.getAvailablePrincipal(principals); + List<String> roles = new ArrayList<String>(); + List<String> permissions = new ArrayList<String>(); + + SysUser user = this.sysUserService.getSysUserByAccount(account); + if(user != null && user.getRoleId() != null) { + roles.add(user.getRoleName()); + + List<BaseRolePage> baseRolePageList = baseRolePageService.getBaseRolePageList(user.getRoleId(), null); + if (baseRolePageList != null && baseRolePageList.size() > 0) { + for (BaseRolePage baseRolePage : baseRolePageList) { + permissions.add(baseRolePage.getPageId()); + } + } + } + + info.addRoles(roles); + info.addStringPermissions(permissions); + return info; + } + + @Override + public void onLogout(PrincipalCollection principals) { + Subject currentUser = SecurityUtils.getSubject(); + currentUser.getSession(true).removeAttribute(Constants.SESSION_USER); + super.onLogout(principals); + } + + /** + * 清除用户缓存 + * @param loginName + */ + public void removeUserCache(String loginName){ + Cache<Object, AuthenticationInfo> cache = getAuthenticationCache(); + if (null != cache){ + cache.remove(loginName); + } + SimplePrincipalCollection principals = new SimplePrincipalCollection(); + principals.add(loginName, super.getName()); + super.clearCachedAuthenticationInfo(principals); + } +} diff --git a/src/main/java/com/nanometer/smartlab/realm/ShiroSpringCache.java b/src/main/java/com/nanometer/smartlab/realm/ShiroSpringCache.java new file mode 100644 index 0000000..c961a51 --- /dev/null +++ b/src/main/java/com/nanometer/smartlab/realm/ShiroSpringCache.java @@ -0,0 +1,113 @@ +/** + * The MIT License (MIT) + * Copyright (c) 2016 Dreamlu (596392912@qq.com). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.nanometer.smartlab.realm; + +import org.apache.log4j.Logger; +import org.apache.shiro.cache.CacheException; +import org.springframework.cache.Cache; +import org.springframework.cache.Cache.ValueWrapper; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +/** + * 使用spring-cache作为shiro缓存 + * + * + */ +@SuppressWarnings("unchecked") +public class ShiroSpringCache<K, V> implements org.apache.shiro.cache.Cache<K, V> { + private static final Logger logger = Logger.getLogger(ShiroSpringCache.class); + + private final Cache cache; + + public ShiroSpringCache(Cache cache) { + if (cache == null) { + throw new IllegalArgumentException("Cache argument cannot be null."); + } + this.cache = cache; + } + + @Override + public V get(K key) throws CacheException { + if (logger.isTraceEnabled()) { + logger.trace("Getting object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass()); + } + ValueWrapper valueWrapper = cache.get(key); + if (valueWrapper == null) { + if (logger.isTraceEnabled()) { + logger.trace("Element for [" + key + "] is null."); + } + return null; + } + return (V) valueWrapper.get(); + } + + @Override + public V put(K key, V value) throws CacheException { + if (logger.isTraceEnabled()) { + logger.trace("Putting object in cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass()); + } + V previous = get(key); + cache.put(key, value); + return previous; + } + + @Override + public V remove(K key) throws CacheException { + if (logger.isTraceEnabled()) { + logger.trace("Removing object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass()); + } + V previous = get(key); + cache.evict(key); + return previous; + } + + @Override + public void clear() throws CacheException { + if (logger.isTraceEnabled()) { + logger.trace("Clearing all objects from cache [" + this.cache.getName() + "]"); + } + cache.clear(); + } + + @Override + public int size() { + return 0; + } + + @Override + public Set<K> keys() { + return Collections.emptySet(); + } + + @Override + public Collection<V> values() { + return Collections.emptySet(); + } + + @Override + public String toString() { + return "ShiroSpringCache [" + this.cache.getName() + "]"; + } +} diff --git a/src/main/java/com/nanometer/smartlab/realm/ShiroSpringCacheManager.java b/src/main/java/com/nanometer/smartlab/realm/ShiroSpringCacheManager.java new file mode 100644 index 0000000..982e707 --- /dev/null +++ b/src/main/java/com/nanometer/smartlab/realm/ShiroSpringCacheManager.java @@ -0,0 +1,63 @@ +/** + * The MIT License (MIT) + * Copyright (c) 2016 Dreamlu (596392912@qq.com). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.nanometer.smartlab.realm; + +import org.apache.log4j.Logger; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheException; +import org.apache.shiro.cache.CacheManager; +import org.apache.shiro.util.Destroyable; + +/** + * 使用spring-cache作为shiro缓存 + * 缓存管理器 + * @author L.cm + * + */ +public class ShiroSpringCacheManager implements CacheManager, Destroyable { + private static final Logger logger = Logger.getLogger(ShiroSpringCacheManager.class); + + private org.springframework.cache.CacheManager cacheManager; + + public org.springframework.cache.CacheManager getCacheManager() { + return cacheManager; + } + + public void setCacheManager(org.springframework.cache.CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + @Override + public <K, V> Cache<K, V> getCache(String name) throws CacheException { + if (logger.isTraceEnabled()) { + logger.trace("Acquiring ShiroSpringCache instance named [" + name + "]"); + } + org.springframework.cache.Cache cache = cacheManager.getCache(name); + return new ShiroSpringCache<K, V>(cache); + } + + @Override + public void destroy() throws Exception { + cacheManager = null; + } + +} diff --git a/src/main/java/com/nanometer/smartlab/service/InterfaceServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/InterfaceServiceImpl.java index d197cf3..2a393df 100644 --- a/src/main/java/com/nanometer/smartlab/service/InterfaceServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/InterfaceServiceImpl.java @@ -22,6 +22,7 @@ import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -39,7 +40,7 @@ public class InterfaceServiceImpl implements InterfaceService { private static Logger logger = Logger.getLogger(ApiAction.class); - + @Lazy @Resource private OpeUseFlowService opeUseFlowService; @Resource diff --git a/src/main/java/com/nanometer/smartlab/service/OpeApplyServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/OpeApplyServiceImpl.java index 4f09cda..9924439 100644 --- a/src/main/java/com/nanometer/smartlab/service/OpeApplyServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/OpeApplyServiceImpl.java @@ -15,6 +15,7 @@ import com.nanometer.smartlab.util.MessageUtil; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.springframework.context.annotation.Lazy; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; @@ -41,10 +42,13 @@ @Resource(name = "opeApplyDao") OpeApplyDao opeApplyDao; + @Lazy @Resource OpeOrderService opeOrderService; + @Lazy @Resource OpeReagentStatusService opeReagentStatusService; + @Lazy @Resource OpeWarehouseReserveService opeWarehouseReserveService; diff --git a/src/main/java/com/nanometer/smartlab/service/OpeOrderServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/OpeOrderServiceImpl.java index 50ce804..ea1518d 100644 --- a/src/main/java/com/nanometer/smartlab/service/OpeOrderServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/OpeOrderServiceImpl.java @@ -17,6 +17,7 @@ import com.nanometer.smartlab.util.MessageUtil; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.springframework.context.annotation.Lazy; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; @@ -49,10 +50,13 @@ private SysSequenceService sysSequenceService; @Resource private OpeApplyService opeApplyService; + @Lazy @Resource private OpeReagentStatusService opeReagentStatusService; + @Lazy @Resource private OpeWarehouseReserveService opeWarehouseReserveService; + @Lazy @Resource private OpeUseFlowService opeUseFlowService; @Resource diff --git a/src/main/java/com/nanometer/smartlab/service/OpeReagentStatusServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/OpeReagentStatusServiceImpl.java index 30b76c3..c3ab8f4 100644 --- a/src/main/java/com/nanometer/smartlab/service/OpeReagentStatusServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/OpeReagentStatusServiceImpl.java @@ -12,6 +12,7 @@ import com.nanometer.smartlab.entity.enumtype.ValidFlag; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.springframework.context.annotation.Lazy; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; @@ -40,9 +41,10 @@ @Resource(name = "opeReagentStatusDao") OpeReagentStatusDao opeReagentStatusDao; - + @Lazy @Resource private OpeWarehouseReserveService opeWarehouseReserveService; + @Lazy @Resource private OpeUseFlowService opeUseFlowService; @Resource diff --git a/src/main/java/com/nanometer/smartlab/service/OpeUseFlowServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/OpeUseFlowServiceImpl.java index 2d7ab3e..e0a4ccb 100644 --- a/src/main/java/com/nanometer/smartlab/service/OpeUseFlowServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/OpeUseFlowServiceImpl.java @@ -55,8 +55,6 @@ @Resource private OpeReagentStatusService opeReagentStatusService; @Resource - private OpeUseFlowService opeUseFlowService; - @Resource private SysReagentService sysReagentService; @Resource private BaseMetaDao baseMetaDao; @@ -389,11 +387,11 @@ for (String statusId : codeTmp) { String code = opeReagentStatusService.getOpeReagentStatus(statusId).getReagentCode(); //此时状态为领用待入库 - opeUseFlowService.updateReceiptNumber(code, receiptNumber); + this.updateReceiptNumber(code, receiptNumber); } }else{ for (String code : codeTmp) { - opeUseFlowService.updateReceiptNumber(code, receiptNumber); + this.updateReceiptNumber(code, receiptNumber); } } @@ -443,11 +441,11 @@ for (String statusId : codeTmp) { String code = opeReagentStatusService.getOpeReagentStatus(statusId).getReagentCode(); //此时状态为领用待入库 - opeUseFlowService.updateReceiptNumber(code, receiptNumber); + this.updateReceiptNumber(code, receiptNumber); } }else{ for (String code : codeTmp) { - opeUseFlowService.updateReceiptNumber(code, receiptNumber); + this.updateReceiptNumber(code, receiptNumber); } } diff --git a/src/main/java/com/nanometer/smartlab/service/OpeWarehouseReserveServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/OpeWarehouseReserveServiceImpl.java index c26f32f..18fc0ef 100644 --- a/src/main/java/com/nanometer/smartlab/service/OpeWarehouseReserveServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/OpeWarehouseReserveServiceImpl.java @@ -48,8 +48,6 @@ @Resource private OpeUseFlowService opeUseFlowService; - @Resource - private OpeWarehouseReserveService opeWarehouseReserveService; @Resource(name="baseMetaDao") private BaseMetaDao baseMetaDao; @@ -596,8 +594,7 @@ @Transactional public void insertOpeWarehouseReserve2(OpeApplyReserve opeApplyReserve, OpeOrder oo) { - OpeWarehouseReserve ope = this.opeWarehouseReserveService - .getOpeWarehouseReserve2(opeApplyReserve.getReagent().getId(), opeApplyReserve.getArticleNumber(),opeApplyReserve.getHouseId()); + OpeWarehouseReserve ope = this.getOpeWarehouseReserve2(opeApplyReserve.getReagent().getId(), opeApplyReserve.getArticleNumber(),opeApplyReserve.getHouseId()); if (ope == null) { ope = new OpeWarehouseReserve(); @@ -619,7 +616,7 @@ opeWarehouseReserveDao.insertOpeWarehouseReserve2(ope); }else { ope.setReserve(ope.getReserve() + opeApplyReserve.getArrivalNum()); - this.opeWarehouseReserveService.updateOpeWarehouseReserve(ope); + this.updateOpeWarehouseReserve(ope); } @@ -686,7 +683,7 @@ List<OpeWarehouseReserve> cacheUpdateList = oar.getCacheUpdateList(); for (OpeWarehouseReserve owr : cacheUpdateList) { //1.根据仓库id和试剂id搜索不同批号的试剂库存 - List<OpeWarehouseReserve> reserveList = opeWarehouseReserveService + List<OpeWarehouseReserve> reserveList = this .selectWarehouseByRidAndArticleNumberAndWarehouse(reagentId, owr.getArticleNumber(), owr.getWarehouseId()); Integer numLeave = owr.getUseNum(); @@ -730,9 +727,9 @@ } - + //更新库存 - opeWarehouseReserveService.updateBtReserve(warehouseReserve.getId(),usedNum); + this.updateBtReserve(warehouseReserve.getId(),usedNum); if (numLeave < 1) { break; } @@ -819,7 +816,7 @@ // 仓库库存update - opeWarehouseReserve = this.opeWarehouseReserveService.getOpeWarehouseReserve2(opeApply.getReagent().getId(), opeApply.getArticleNumber(),opeApply.getHouseId()); + opeWarehouseReserve = this.getOpeWarehouseReserve2(opeApply.getReagent().getId(), opeApply.getArticleNumber(),opeApply.getHouseId()); if (opeWarehouseReserve == null) { opeWarehouseReserve = new OpeWarehouseReserve(); opeWarehouseReserve.setReagentId(opeApply.getReagent().getId()); @@ -830,9 +827,9 @@ } opeWarehouseReserve.setReserve(opeWarehouseReserve.getReserve() + opeApply.getArrivalNum()); if (StringUtils.isBlank(opeWarehouseReserve.getId())) { - this.opeWarehouseReserveService.insertOpeWarehouseReserve(opeWarehouseReserve); + this.insertOpeWarehouseReserve(opeWarehouseReserve); } else { - this.opeWarehouseReserveService.updateOpeWarehouseReserve(opeWarehouseReserve); + this.updateOpeWarehouseReserve(opeWarehouseReserve); } } } diff --git a/src/main/java/com/nanometer/smartlab/service/SysControllerServiceImpl.java b/src/main/java/com/nanometer/smartlab/service/SysControllerServiceImpl.java index 4c5aa0e..5a6321b 100644 --- a/src/main/java/com/nanometer/smartlab/service/SysControllerServiceImpl.java +++ b/src/main/java/com/nanometer/smartlab/service/SysControllerServiceImpl.java @@ -38,8 +38,6 @@ SysControllerDao sysControllerDao; @Resource(name = "sysLaboratoryContainerDao") SysLaboratoryContainerDao sysLaboratoryContainerDao; - @Resource(name = "sysControllerService") - SysControllerService sysControllerService; @Resource(name = "baseMetaService") BaseMetaService baseMetaService; @Override @@ -62,7 +60,7 @@ throw new BusinessException(ExceptionEnumCode.DB_ERR, MessageUtil.getMessageByCode(ExceptionEnumCode.DB_ERR.getCode()), e); } - + } @Override @@ -114,7 +112,7 @@ @Override public void uploadFile(FileUploadEvent event) throws Exception{ - List<SysController> sysControllers=sysControllerService.getAllControllerList(); + List<SysController> sysControllers=this.getAllControllerList(); List<BaseMeta> typeList=baseMetaService.getBaseMetaList("controller_type"); //主控名字和条码 HashSet<String> controllerInfo = new HashSet<>(); @@ -196,7 +194,7 @@ sysController.setControllerCode(controlCode); sysController.setControllerName(controlName); sysController.setType(typeMap.get(controlType)); - sysControllerService.insertSysController(sysController); + this.insertSysController(sysController); controllerInfo.add(controlName); controllerInfo.add(controlCode); } diff --git a/src/main/java/com/nanometer/smartlab/util/Validator.java b/src/main/java/com/nanometer/smartlab/util/Validator.java new file mode 100644 index 0000000..ccc4e60 --- /dev/null +++ b/src/main/java/com/nanometer/smartlab/util/Validator.java @@ -0,0 +1,48 @@ +package com.nanometer.smartlab.util; + +public class Validator { + public static String filter(String value) { + if (value == null) { + return null; + } + StringBuffer result = new StringBuffer(value.length()); + for (int i = 0; i < value.length(); ++i){ + switch (value.charAt(i)) { + case '<': + result.append("<"); + break; + case '>': + result.append(">"); + break; + case '"': + result.append("""); + break; + case '\'': + result.append("'"); + break; + case '%': + result.append("%"); + break; + case ';': + result.append(";"); + break; + case '(': + result.append("("); + break; + case ')': + result.append(")"); + break; + case '&': + result.append("&"); + break; + case '+': + result.append("+"); + break; + default: + result.append(value.charAt(i)); + break; + } + } + return result.toString().replaceAll("\\\\","").replaceAll("/", ""); + } +} diff --git a/src/main/java/org/apache/shiro/web/filter/InvalidRequestFilter.java b/src/main/java/org/apache/shiro/web/filter/InvalidRequestFilter.java index 48fcb2e..b697690 100644 --- a/src/main/java/org/apache/shiro/web/filter/InvalidRequestFilter.java +++ b/src/main/java/org/apache/shiro/web/filter/InvalidRequestFilter.java @@ -86,50 +86,50 @@ ctx = WebUtils.toHttp(request).getContextPath(); } // 登录url拼接的jsessionId进行放行 - if(uri.startsWith(ctx + this.getLoginUrl() + ";jsessionid=") || - uri.startsWith(ctx + this.getLoginUrl() + "%3bjsessionid=") || - uri.startsWith(ctx + this.getLoginUrl() + "%3Bjsessionid=") || - uri.startsWith(ctx + "/javax.faces.resource/mybootstrap.css.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/mybootstrap.css.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/mybootstrap.css.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/default.css.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/default.css.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/default.css.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/components.css.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/components.css.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/components.css.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery-plugins.js.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery-plugins.js.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery-plugins.js.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery.js.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery.js.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery.js.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/core.js.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/core.js.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/core.js.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/extra.js.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/extra.js.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/extra.js.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/resources/images/logo1.png;jsessionid=")|| - uri.startsWith(ctx + "/resources/images/logo1.png%3bjsessionid=")|| - uri.startsWith(ctx + "/resources/images/logo1.png%3Bjsessionid=")|| - - uri.startsWith(ctx + "/javax.faces.resource/components.js.xhtml;jsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/components.js.xhtml%3bjsessionid=")|| - uri.startsWith(ctx + "/javax.faces.resource/components.js.xhtml%3Bjsessionid=")|| - - uri.startsWith(ctx + "/resources/images/logo.png;jsessionid=")|| - uri.startsWith(ctx + "/resources/images/logo.png%3bjsessionid=")|| - uri.startsWith(ctx + "/resources/images/logo.png%3Bjsessionid=")) { - return false; - } +// if(uri.startsWith(ctx + this.getLoginUrl() + ";jsessionid=") || +// uri.startsWith(ctx + this.getLoginUrl() + "%3bjsessionid=") || +// uri.startsWith(ctx + this.getLoginUrl() + "%3Bjsessionid=") || +// uri.startsWith(ctx + "/javax.faces.resource/mybootstrap.css.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/mybootstrap.css.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/mybootstrap.css.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/default.css.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/default.css.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/default.css.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/components.css.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/components.css.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/components.css.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery-plugins.js.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery-plugins.js.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery-plugins.js.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery.js.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery.js.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/jquery/jquery.js.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/core.js.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/core.js.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/core.js.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/extra.js.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/extra.js.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/extra.js.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/resources/images/logo1.png;jsessionid=")|| +// uri.startsWith(ctx + "/resources/images/logo1.png%3bjsessionid=")|| +// uri.startsWith(ctx + "/resources/images/logo1.png%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/javax.faces.resource/components.js.xhtml;jsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/components.js.xhtml%3bjsessionid=")|| +// uri.startsWith(ctx + "/javax.faces.resource/components.js.xhtml%3Bjsessionid=")|| +// +// uri.startsWith(ctx + "/resources/images/logo.png;jsessionid=")|| +// uri.startsWith(ctx + "/resources/images/logo.png%3bjsessionid=")|| +// uri.startsWith(ctx + "/resources/images/logo.png%3Bjsessionid=")) { +// return false; +// } return SEMICOLON.stream().anyMatch(uri::contains); } return false; diff --git a/src/main/java/org/springframework/web/filter/DelegatingFilterProxy.java b/src/main/java/org/springframework/web/filter/DelegatingFilterProxy.java new file mode 100644 index 0000000..6c74c45 --- /dev/null +++ b/src/main/java/org/springframework/web/filter/DelegatingFilterProxy.java @@ -0,0 +1,409 @@ +/* + * Copyright 2002-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.filter; + +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Proxy for a standard Servlet Filter, delegating to a Spring-managed bean that + * implements the Filter interface. Supports a "targetBeanName" filter init-param + * in {@code web.xml}, specifying the name of the target bean in the Spring + * application context. + * + * <p>{@code web.xml} will usually contain a {@code DelegatingFilterProxy} definition, + * with the specified {@code filter-name} corresponding to a bean name in + * Spring's root application context. All calls to the filter proxy will then + * be delegated to that bean in the Spring context, which is required to implement + * the standard Servlet Filter interface. + * + * <p>This approach is particularly useful for Filter implementation with complex + * setup needs, allowing to apply the full Spring bean definition machinery to + * Filter instances. Alternatively, consider standard Filter setup in combination + * with looking up service beans from the Spring root application context. + * + * <p><b>NOTE:</b> The lifecycle methods defined by the Servlet Filter interface + * will by default <i>not</i> be delegated to the target bean, relying on the + * Spring application context to manage the lifecycle of that bean. Specifying + * the "targetFilterLifecycle" filter init-param as "true" will enforce invocation + * of the {@code Filter.init} and {@code Filter.destroy} lifecycle methods + * on the target bean, letting the servlet container manage the filter lifecycle. + * + * <p>As of Spring 3.1, {@code DelegatingFilterProxy} has been updated to optionally accept + * constructor parameters when using Servlet 3.0's instance-based filter registration + * methods, usually in conjunction with Spring 3.1's + * {@link org.springframework.web.WebApplicationInitializer} SPI. These constructors allow + * for providing the delegate Filter bean directly, or providing the application context + * and bean name to fetch, avoiding the need to look up the application context from the + * ServletContext. + * + * <p>This class was originally inspired by Spring Security's {@code FilterToBeanProxy} + * class, written by Ben Alex. + * + * @author Juergen Hoeller + * @author Sam Brannen + * @author Chris Beams + * @since 1.2 + * @see #setTargetBeanName + * @see #setTargetFilterLifecycle + * @see Filter#doFilter + * @see Filter#init + * @see Filter#destroy + * @see #DelegatingFilterProxy(Filter) + * @see #DelegatingFilterProxy(String) + * @see #DelegatingFilterProxy(String, WebApplicationContext) + * @see org.springframework.web.WebApplicationInitializer + */ +public class DelegatingFilterProxy extends GenericFilterBean { + + private String contextAttribute; + + private WebApplicationContext webApplicationContext; + + private String targetBeanName; + + private boolean targetFilterLifecycle = false; + + private volatile Filter delegate; + + private final Object delegateMonitor = new Object(); + + + /** + * Create a new {@code DelegatingFilterProxy}. For traditional (pre-Servlet 3.0) use + * in {@code web.xml}. + * @see #setTargetBeanName(String) + */ + public DelegatingFilterProxy() { + } + + /** + * Create a new {@code DelegatingFilterProxy} with the given {@link Filter} delegate. + * Bypasses entirely the need for interacting with a Spring application context, + * specifying the {@linkplain #setTargetBeanName target bean name}, etc. + * <p>For use in Servlet 3.0+ environments where instance-based registration of + * filters is supported. + * @param delegate the {@code Filter} instance that this proxy will delegate to and + * manage the lifecycle for (must not be {@code null}). + * @see #doFilter(ServletRequest, ServletResponse, FilterChain) + * @see #invokeDelegate(Filter, ServletRequest, ServletResponse, FilterChain) + * @see #destroy() + * @see #setEnvironment(org.springframework.core.env.Environment) + */ + public DelegatingFilterProxy(Filter delegate) { + Assert.notNull(delegate, "Delegate Filter must not be null"); + this.delegate = delegate; + } + + /** + * Create a new {@code DelegatingFilterProxy} that will retrieve the named target + * bean from the Spring {@code WebApplicationContext} found in the {@code ServletContext} + * (either the 'root' application context or the context named by + * {@link #setContextAttribute}). + * <p>For use in Servlet 3.0+ environments where instance-based registration of + * filters is supported. + * <p>The target bean must implement the standard Servlet Filter. + * @param targetBeanName name of the target filter bean to look up in the Spring + * application context (must not be {@code null}). + * @see #findWebApplicationContext() + * @see #setEnvironment(org.springframework.core.env.Environment) + */ + public DelegatingFilterProxy(String targetBeanName) { + this(targetBeanName, null); + } + + /** + * Create a new {@code DelegatingFilterProxy} that will retrieve the named target + * bean from the given Spring {@code WebApplicationContext}. + * <p>For use in Servlet 3.0+ environments where instance-based registration of + * filters is supported. + * <p>The target bean must implement the standard Servlet Filter interface. + * <p>The given {@code WebApplicationContext} may or may not be refreshed when passed + * in. If it has not, and if the context implements {@link ConfigurableApplicationContext}, + * a {@link ConfigurableApplicationContext#refresh() refresh()} will be attempted before + * retrieving the named target bean. + * <p>This proxy's {@code Environment} will be inherited from the given + * {@code WebApplicationContext}. + * @param targetBeanName name of the target filter bean in the Spring application + * context (must not be {@code null}). + * @param wac the application context from which the target filter will be retrieved; + * if {@code null}, an application context will be looked up from {@code ServletContext} + * as a fallback. + * @see #findWebApplicationContext() + * @see #setEnvironment(org.springframework.core.env.Environment) + */ + public DelegatingFilterProxy(String targetBeanName, WebApplicationContext wac) { + Assert.hasText(targetBeanName, "Target Filter bean name must not be null or empty"); + this.setTargetBeanName(targetBeanName); + this.webApplicationContext = wac; + if (wac != null) { + this.setEnvironment(wac.getEnvironment()); + } + } + + /** + * Set the name of the ServletContext attribute which should be used to retrieve the + * {@link WebApplicationContext} from which to load the delegate {@link Filter} bean. + */ + public void setContextAttribute(String contextAttribute) { + this.contextAttribute = contextAttribute; + } + + /** + * Return the name of the ServletContext attribute which should be used to retrieve the + * {@link WebApplicationContext} from which to load the delegate {@link Filter} bean. + */ + public String getContextAttribute() { + return this.contextAttribute; + } + + /** + * Set the name of the target bean in the Spring application context. + * The target bean must implement the standard Servlet Filter interface. + * <p>By default, the {@code filter-name} as specified for the + * DelegatingFilterProxy in {@code web.xml} will be used. + */ + public void setTargetBeanName(String targetBeanName) { + this.targetBeanName = targetBeanName; + } + + /** + * Return the name of the target bean in the Spring application context. + */ + protected String getTargetBeanName() { + return this.targetBeanName; + } + + /** + * Set whether to invoke the {@code Filter.init} and + * {@code Filter.destroy} lifecycle methods on the target bean. + * <p>Default is "false"; target beans usually rely on the Spring application + * context for managing their lifecycle. Setting this flag to "true" means + * that the servlet container will control the lifecycle of the target + * Filter, with this proxy delegating the corresponding calls. + */ + public void setTargetFilterLifecycle(boolean targetFilterLifecycle) { + this.targetFilterLifecycle = targetFilterLifecycle; + } + + /** + * Return whether to invoke the {@code Filter.init} and + * {@code Filter.destroy} lifecycle methods on the target bean. + */ + protected boolean isTargetFilterLifecycle() { + return this.targetFilterLifecycle; + } + + + @Override + protected void initFilterBean() throws ServletException { + synchronized (this.delegateMonitor) { + if (this.delegate == null) { + // If no target bean name specified, use filter name. + if (this.targetBeanName == null) { + this.targetBeanName = getFilterName(); + } + // Fetch Spring root application context and initialize the delegate early, + // if possible. If the root application context will be started after this + // filter proxy, we'll have to resort to lazy initialization. + WebApplicationContext wac = findWebApplicationContext(); + if (wac != null) { + this.delegate = initDelegate(wac); + } + } + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + String referer = ((HttpServletRequest)request).getHeader("Referer"); + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(request.getScheme()).append("://").append(request.getServerName()); + if(referer != null && !referer.equals("") ){ + if(referer.lastIndexOf(String.valueOf(stringBuffer)) != 0){ + HttpServletResponse httpResp1 = (HttpServletResponse)response; + httpResp1.setStatus(500); + httpResp1.setContentType("text/html; charset=utf-8"); + httpResp1.getWriter().write("系统不支持当前域名的访问!"); + return; + } + } + + String method = ((HttpServletRequest)request).getMethod(); + if (method.toUpperCase().equals("OPTIONS")){ + HttpServletResponse httpResp1 = (HttpServletResponse)response; + httpResp1.setStatus(500); + httpResp1.setContentType("text/html; charset=utf-8"); + httpResp1.getWriter().write("系统不支持访问!"); + return; + } + + String contentType = ((HttpServletRequest)request).getHeader("Content-Type"); + if ((method.toUpperCase().equals("GET") && !StringUtils.isEmpty(contentType) && contentType.contains("form"))|| + (StringUtils.isEmpty(contentType) && method.toUpperCase().equals("POST"))){ + HttpServletResponse httpResp1 = (HttpServletResponse)response; + httpResp1.setStatus(500); + httpResp1.setContentType("text/html; charset=utf-8"); + httpResp1.getWriter().write("系统不支持访问!"); + return; + } + + + HttpServletRequest httpReq = (HttpServletRequest) request; + HttpServletResponse httpRes = (HttpServletResponse) response; + + /**禁止缓存**/ + httpRes.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + httpRes.setHeader("Pragma", "no-cache"); + httpRes.setHeader("X-Content-Type-Options", "nosniff"); + httpRes.setHeader("X-XSS-Protection", "1"); + httpRes.setHeader("strict-transport-security", "max-age=31536000"); + httpRes.setHeader("X-Frame-Options", "DENY"); + + //安全测评需要,如影响使用请注释掉 + if(httpReq.getRequestURI().contains("javax.faces.resource")){ + httpRes.setHeader("Content-Security-Policy", "default-src 'self';script-src 'self';frame-ancestors 'self';"); + } + + // Lazily initialize the delegate if necessary. + Filter delegateToUse = this.delegate; + if (delegateToUse == null) { + synchronized (this.delegateMonitor) { + delegateToUse = this.delegate; + if (delegateToUse == null) { + WebApplicationContext wac = findWebApplicationContext(); + if (wac == null) { + throw new IllegalStateException("No WebApplicationContext found: " + + "no ContextLoaderListener or DispatcherServlet registered?"); + } + delegateToUse = initDelegate(wac); + } + this.delegate = delegateToUse; + } + } + + // Let the delegate perform the actual doFilter operation. + invokeDelegate(delegateToUse, request, response, filterChain); + } + + @Override + public void destroy() { + Filter delegateToUse = this.delegate; + if (delegateToUse != null) { + destroyDelegate(delegateToUse); + } + } + + + /** + * Return the {@code WebApplicationContext} passed in at construction time, if available. + * Otherwise, attempt to retrieve a {@code WebApplicationContext} from the + * {@code ServletContext} attribute with the {@linkplain #setContextAttribute + * configured name} if set. Otherwise look up a {@code WebApplicationContext} under + * the well-known "root" application context attribute. The + * {@code WebApplicationContext} must have already been loaded and stored in the + * {@code ServletContext} before this filter gets initialized (or invoked). + * <p>Subclasses may override this method to provide a different + * {@code WebApplicationContext} retrieval strategy. + * @return the {@code WebApplicationContext} for this proxy, or {@code null} if not found + * @see #DelegatingFilterProxy(String, WebApplicationContext) + * @see #getContextAttribute() + * @see WebApplicationContextUtils#getWebApplicationContext(ServletContext) + * @see WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + */ + protected WebApplicationContext findWebApplicationContext() { + if (this.webApplicationContext != null) { + // The user has injected a context at construction time -> use it... + if (this.webApplicationContext instanceof ConfigurableApplicationContext) { + ConfigurableApplicationContext cac = (ConfigurableApplicationContext) this.webApplicationContext; + if (!cac.isActive()) { + // The context has not yet been refreshed -> do so before returning it... + cac.refresh(); + } + } + return this.webApplicationContext; + } + String attrName = getContextAttribute(); + if (attrName != null) { + return WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName); + } + else { + return WebApplicationContextUtils.findWebApplicationContext(getServletContext()); + } + } + + /** + * Initialize the Filter delegate, defined as bean the given Spring + * application context. + * <p>The default implementation fetches the bean from the application context + * and calls the standard {@code Filter.init} method on it, passing + * in the FilterConfig of this Filter proxy. + * @param wac the root application context + * @return the initialized delegate Filter + * @throws ServletException if thrown by the Filter + * @see #getTargetBeanName() + * @see #isTargetFilterLifecycle() + * @see #getFilterConfig() + * @see Filter#init(FilterConfig) + */ + protected Filter initDelegate(WebApplicationContext wac) throws ServletException { + Filter delegate = wac.getBean(getTargetBeanName(), Filter.class); + if (isTargetFilterLifecycle()) { + delegate.init(getFilterConfig()); + } + return delegate; + } + + /** + * Actually invoke the delegate Filter with the given request and response. + * @param delegate the delegate Filter + * @param request the current HTTP request + * @param response the current HTTP response + * @param filterChain the current FilterChain + * @throws ServletException if thrown by the Filter + * @throws IOException if thrown by the Filter + */ + protected void invokeDelegate( + Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + + delegate.doFilter(request, response, filterChain); + } + + /** + * Destroy the Filter delegate. + * Default implementation simply calls {@code Filter.destroy} on it. + * @param delegate the Filter delegate (never {@code null}) + * @see #isTargetFilterLifecycle() + * @see Filter#destroy() + */ + protected void destroyDelegate(Filter delegate) { + if (isTargetFilterLifecycle()) { + delegate.destroy(); + } + } + +} diff --git a/src/main/webapp/WEB-INF/spring-mvc.xml b/src/main/webapp/WEB-INF/spring-mvc.xml index 223f060..f4d9967 100644 --- a/src/main/webapp/WEB-INF/spring-mvc.xml +++ b/src/main/webapp/WEB-INF/spring-mvc.xml @@ -11,12 +11,13 @@ http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd - http://www.springframework.org/schema/task + http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd"> <context:component-scan base-package="com.nanometer.smartlab.api"/> + <context:component-scan base-package="com.nanometer.smartlab.controller"/> <!-- 静态资源(js、image等)的访问 --> <mvc:default-servlet-handler/> @@ -51,6 +52,6 @@ </bean> <mvc:cors> - <mvc:mapping path="/**" allowed-origins="*" allow-credentials="true" max-age="1800" allowed-methods="GET,POST,OPTIONS"/> + <mvc:mapping path="/**" allowed-origins="*" allow-credentials="true" max-age="1800" allowed-methods="GET,POST"/> </mvc:cors> -</beans> \ No newline at end of file +</beans> diff --git a/src/main/webapp/WEB-INF/spring-shiro.xml b/src/main/webapp/WEB-INF/spring-shiro.xml index 65070e9..357bd34 100644 --- a/src/main/webapp/WEB-INF/spring-shiro.xml +++ b/src/main/webapp/WEB-INF/spring-shiro.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:util="http://www.springframework.org/schema/util" + xmlns:util="http://www.springframework.org/schema/util" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> @@ -60,8 +60,9 @@ </bean> <!-- Cache Manager --> - <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> + <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcacheManager"/> + <property name="transactionAware" value="true"/> </bean> <!-- 如果有多个ehcacheManager要在bean加上p:shared="true" --> @@ -69,9 +70,30 @@ <property name="configLocation" value="WEB-INF/ehcache.xml"/> </bean> + <!-- cache注解,和spring-redis.xml中的只能使用一个 --> + <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/> + + <bean id="shiroSpringCacheManager" class="com.nanometer.smartlab.realm.ShiroSpringCacheManager"> + <property name="cacheManager" ref="cacheManager"></property> + </bean> + <!--session manager--> <bean id="sessionManager" - class="org.apache.shiro.web.session.mgt.ServletContainerSessionManager"> + class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> + <!-- url上带sessionId 默认为true --> + <property name="sessionIdUrlRewritingEnabled" value="false"/> + <property name="sessionDAO" ref="sessionDAO"/> + <!-- cookie名称 --> + <property name="sessionIdCookie.name" value="gasid"/> + <!-- cookie生效路径 --> + <property name="sessionIdCookie.path" value="/"/> + </bean> + + <!-- 会话DAO 用于会话的CRUD --> + <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"> + <!-- Session缓存名字,默认就是shiro-activeSessionCache --> + <property name="activeSessionsCacheName" value="activeSessionCache"/> + <property name="cacheManager" ref="shiroSpringCacheManager"/> </bean> <!--credentialsMatcher 密码加密--> @@ -82,9 +104,9 @@ </bean> <!--自定义 Realm--> - <bean id="authorizationRealm" class="com.nanometer.smartlab.realm.AuthorizationRealm"> - <property name="credentialsMatcher" ref="md5Matcher"/> - + <bean id="authorizationRealm" class="com.nanometer.smartlab.realm.ShiroDbRealm"> + <constructor-arg index="0" name="cacheManager" ref="shiroSpringCacheManager"/> + <constructor-arg index="1" name="matcher" ref="credentialsMatcher"/> <!-- 启用身份验证缓存,即缓存AuthenticationInfo信息,默认false --> <property name="authenticationCachingEnabled" value="true"/> <!-- 缓存AuthenticationInfo信息的缓存名称 --> @@ -92,12 +114,21 @@ <!-- 缓存AuthorizationInfo信息的缓存名称 --> <property name="authorizationCacheName" value="authorizationCache"/> </bean> + <!-- 密码错误5次锁定5min --> + <bean id="credentialsMatcher" class="com.nanometer.smartlab.realm.RetryLimitCredentialsMatcher"> + <constructor-arg ref="shiroSpringCacheManager"/> + <property name="retryLimitCacheName" value="fivMin"/> + <!-- 密码加密 1次md5,增强密码可修改此处 --> + <property name="hashAlgorithmName" value="MD5"/> + <property name="storedCredentialsHexEncoded" value="true"/> + <property name="hashIterations" value="1"/> + </bean> <!-- Security Manager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="authorizationRealm"/> <property name="rememberMeManager" ref="rememberMeManager"/> - <property name="cacheManager" ref="cacheManager"/> + <property name="cacheManager" ref="shiroSpringCacheManager"/> <property name="sessionManager" ref="sessionManager"/> </bean> diff --git a/src/main/webapp/WEB-INF/test/test.properties b/src/main/webapp/WEB-INF/test/test.properties index 36ee8bd..15a5f91 100644 --- a/src/main/webapp/WEB-INF/test/test.properties +++ b/src/main/webapp/WEB-INF/test/test.properties @@ -2,10 +2,9 @@ jdbc.username=root jdbc.password=GKHY@root20201! -#\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD institute.id = 2 institute.name = \u4E2D\u56FD\u79D1\u5B66\u9662\u82CF\u5DDE\u7EB3\u7C73\u6280\u672F\u4E0E\u7EB3\u7C73\u4EFF\u751F\u7814\u7A76\u6240 -institute.url = http://sinanoaq.com:8050 +institute.url = https://sinanoaq.cn:8002 institute.app.id = wx81a00e3350861b25 institute.app.secret = c307d394875af2cbbe25e01b9e43dcb2 alarm.url = http://sinanoaq.com/daping/sendWarnInfo.json diff --git a/src/main/webapp/index.xhtml b/src/main/webapp/index.xhtml index 406de33..97bb7eb 100644 --- a/src/main/webapp/index.xhtml +++ b/src/main/webapp/index.xhtml @@ -41,15 +41,15 @@ <p:panelGrid columns="1" styleClass="content"> <p:outputLabel value="原密码"></p:outputLabel> <p:password value="#{userMngController.oriPassword}" maxlength="100" - required="true" requiredMessage="请输入原密码"></p:password> + required="true" requiredMessage="请输入原密码" autocomplete="off"></p:password> <p:outputLabel value="新密码(必须是8位以上且包含大小写和特殊字符)"></p:outputLabel> <p:password value="#{userMngController.newPassword}" maxlength="100" - required="true" requiredMessage="请输入新密码"></p:password> + required="true" requiredMessage="请输入新密码" autocomplete="off"></p:password> <p:outputLabel value="确认密码"></p:outputLabel> <p:password value="#{userMngController.newPasswordSecond}" maxlength="100" - required="true" requiredMessage="请输入确认密码"></p:password> + required="true" requiredMessage="请输入确认密码" autocomplete="off"></p:password> </p:panelGrid> <p:panel styleClass="btn"> <p:commandButton value="修改" actionListener="#{userMngController.updatePasswordAction}" @@ -68,15 +68,15 @@ <p:panelGrid columns="1" styleClass="content"> <p:outputLabel value="原密码"></p:outputLabel> <p:password value="#{userMngController.oriPassword}" maxlength="100" - required="true" requiredMessage="请输入原密码"></p:password> + required="true" requiredMessage="请输入原密码" autocomplete="off"></p:password> <p:outputLabel value="新密码(必须是8位以上且包含大小写和特殊字符)"></p:outputLabel> <p:password value="#{userMngController.newPassword}" maxlength="100" - required="true" requiredMessage="请输入新密码"></p:password> + required="true" requiredMessage="请输入新密码" autocomplete="off"></p:password> <p:outputLabel value="确认密码"></p:outputLabel> <p:password value="#{userMngController.newPasswordSecond}" maxlength="100" - required="true" requiredMessage="请输入确认密码"></p:password> + required="true" requiredMessage="请输入确认密码" autocomplete="off"></p:password> </p:panelGrid> <p:panel styleClass="btn"> <p:commandButton value="修改" actionListener="#{userMngController.updatePasswordAction}" diff --git a/src/main/webapp/login.xhtml b/src/main/webapp/login.xhtml index 478242c..2d7cdce 100644 --- a/src/main/webapp/login.xhtml +++ b/src/main/webapp/login.xhtml @@ -50,7 +50,7 @@ <div> <p:outputLabel value="密码" styleClass="pwd-label"></p:outputLabel> - <p:password value="#{loginController.loginPwd}" required="true" requiredMessage="请输入密码"></p:password> + <p:password value="#{loginController.loginPwd}" required="true" requiredMessage="请输入密码" autocomplete="off"></p:password> </div> <p:commandButton value="登录" ajax="false" action="#{loginController.login}" styleClass="save-button"></p:commandButton> </div> @@ -59,14 +59,8 @@ </div> <div class="login-footer"> - <!--<p:graphicImage value="/resources/images/logo2.png"></p:graphicImage>--> - Copyright © 2017 ${institute.name} - <!--<p:commandLink id="nonAjax" src="http:beian.miit.gov.cn/" ajax="false"> - <h:outputText value="苏ICP备13012319号-1" /> - </p:commandLink>--> <a href="http://beian.miit.gov.cn">苏ICP备10220403号-6</a> - </div> </h:body> </html> diff --git a/src/main/webapp/user_mng.xhtml b/src/main/webapp/user_mng.xhtml index 09ccb1b..b133e54 100644 --- a/src/main/webapp/user_mng.xhtml +++ b/src/main/webapp/user_mng.xhtml @@ -187,8 +187,7 @@ <p:outputLabel value="密码" ></p:outputLabel> <p:password value="#{userMngController.sysUser.password}" maxlength="100" - requiredMessage="请输入密码" - ></p:password> + requiredMessage="请输入密码" autocomplete="off"></p:password> <p:outputLabel value="电话"></p:outputLabel> <p:inputText value="#{userMngController.sysUser.phone}" maxlength="30"></p:inputText> -- Gitblit v1.9.2