Browse Source

fix:xss配置默认更新,对 upload进行拦截处理 类,配置 Shiro 过滤器、安全管理器、会话管理等
- 添加 EditorStateBean- 配置登录、权限过滤器和自定义 Realm
- 设置会话管理和 Cookie

msgroup 1 month ago
parent
commit
7a012f89cb

+ 70 - 0
src/main/java/net/mingsoft/cms/bean/EditorStateBean.java

@@ -0,0 +1,70 @@
+/**
+ * The MIT License (MIT)
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 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 net.mingsoft.cms.bean;
+
+import cn.hutool.json.JSONUtil;
+
+import java.util.HashMap;
+
+/**
+ * 百度编辑器状态实体类
+ * 返回类型一般为大概两种如:{state: "SUCCESS", url:"", type:"",...},{state: "info"}用来返回错误信息
+ */
+public class EditorStateBean extends HashMap<String, Object> {
+
+    /**
+     * 状态
+     */
+    private boolean state  = true;
+
+    /**
+     * 状态信息,一般用来返回错误信息
+     */
+    private String info;
+
+    public EditorStateBean() {
+    }
+
+    public EditorStateBean(boolean state) {
+        this.state = state;
+    }
+
+    public EditorStateBean(boolean state, String info) {
+        this.state = state;
+        this.info = info;
+    }
+
+    public boolean isSuccess() {
+        return this.state;
+    }
+
+    @Override
+    public String toString() {
+        if (this.state) {
+            this.put("state", "SUCCESS");
+        } else {
+            this.put("state", this.info);
+        }
+        return JSONUtil.toJsonStr(this);
+    }
+
+}

+ 242 - 0
src/main/java/net/mingsoft/config/ShiroConfig.java

@@ -0,0 +1,242 @@
+/**
+ * The MIT License (MIT)
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 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 net.mingsoft.config;
+
+import jakarta.annotation.Resource;
+import jakarta.servlet.Filter;
+import net.mingsoft.basic.filter.ShiroLoginFilter;
+import net.mingsoft.basic.filter.ShiroRoleFilter;
+import net.mingsoft.basic.realm.CustomModularRealmAuthenticator;
+import net.mingsoft.basic.realm.ManagerAuthRealm;
+import net.mingsoft.basic.strategy.ILoginStrategy;
+import net.mingsoft.basic.strategy.IModelStrategy;
+import net.mingsoft.basic.strategy.ManagerLoginStrategy;
+import net.mingsoft.basic.strategy.ManagerModelStrategy;
+import org.apache.shiro.authc.Authenticator;
+import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.servlet.SimpleCookie;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+@Configuration
+public class ShiroConfig {
+
+	@Autowired(required = false)
+	MSProperties msProperties;
+
+	@Resource
+	ServerProperties serverProperties;
+
+	/**
+	 * 开启Shiro的注解(如@RequiresRoles , @RequiresPermissions),需借助SspringAOP扫描使用Sshiro注解的类,并在必要时进行安全逻辑验证
+	 * 配置以下两个bean(Defaul tAdvisorAutoProxyCreator和uthorizat ionAttributeSourceAdvisor)即可实现此功能
+	 */
+	@Bean
+	public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
+		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+		advisorAutoProxyCreator.setProxyTargetClass(true);
+		return advisorAutoProxyCreator;
+	}
+
+	/**
+	 * 开启shiro aop注解支持
+	 * 使用代理方式;所以需要开启代码支持
+	 * @param securityManager
+	 */
+	@Bean
+	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
+		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
+		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
+		return authorizationAttributeSourceAdvisor;
+	}
+
+	@Bean
+	public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
+			@Autowired(required = false) DefaultWebSecurityManager securityManager) {
+		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+		advisor.setSecurityManager(securityManager);
+		return advisor;
+	}
+
+	@Bean
+	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
+		DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+		autoProxyCreator.setProxyTargetClass(true);
+		return autoProxyCreator;
+	}
+
+	@Bean(name = "shiroFilterFactoryBean")
+	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
+		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+		// 必须设置 SecurityManager
+		shiroFilterFactoryBean.setSecurityManager(securityManager);
+		// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
+		shiroFilterFactoryBean.setLoginUrl(MSProperties.manager.path + "/login.do");
+		// 设置无权限时跳转的 url;
+		shiroFilterFactoryBean.setUnauthorizedUrl(MSProperties.manager.path + "/404.do");
+
+
+		Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
+		filters.put("authc",new ShiroLoginFilter());
+		// 依赖会员后需放开104行,107行
+		// PeopleLoginFilter会员登录过滤器,在这里people/**接口都会拦截校验是否登录
+		// filters.put("pauth",new PeopleLoginFilter(MSProperties.people.loginUrl));
+		// 角色校验过滤器最终会在对应的reaml中的hasRole校验,可以在ShiroRoleFilter中自定义一些操作
+		 filters.put("managerRoles", new ShiroRoleFilter(MSProperties.manager.path  + "/login.do"));
+		// filters.put("peopleRoles", new ShiroRoleFilter(MSProperties.people.loginUrl));
+
+		// 设置拦截器
+		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
+		// 游客,开发权限
+		filterChainDefinitionMap.put("/static/**", "anon");
+		filterChainDefinitionMap.put("/html/**", "anon");
+		// 开放登陆接口
+		filterChainDefinitionMap.put(MSProperties.manager.path + "/login.do", "anon");
+		filterChainDefinitionMap.put(MSProperties.manager.path + "/checkLogin.do", "anon");
+		// 其余接口一律拦截
+		// 主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
+		// 依赖会员后,放开123行以及202-205行
+		// roles[**]中的**值必须和对应的Reaml赋予当前登录的Roles名称一致,然后值必须时CustomUserNamePasswordToken.AuthType中的值,如果这里值和对应Reaml值不一致则会出现无法访问情况
+		filterChainDefinitionMap.put(msProperties.getManager().path + "/**", "authc,managerRoles[MANAGER]");
+		// filterChainDefinitionMap.put("/people/**", "pauth,peopleRoles[PEOPLE]");
+
+		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+		return shiroFilterFactoryBean;
+	}
+
+	/**
+	 * 注入 securityManager
+	 */
+	@Bean("securityManager")
+	public DefaultWebSecurityManager securityManager(List<Realm> realms, Authenticator authenticator, DefaultWebSessionManager sessionManager) {
+		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+		securityManager.setSessionManager(sessionManager);
+		securityManager.setAuthenticator(authenticator);
+		//集群环境下使用redis共享session用下行代码
+//        securityManager.setCacheManager(shiroRedisCacheManager);
+		// 设置realm
+		securityManager.setRealms(realms);
+		return securityManager;
+	}
+
+	/**
+	 * 重写defaultWebSessionManager,防止url拼接jsessionid
+	 * @return
+	 */
+	@Bean
+	public DefaultWebSessionManager defaultWebSessionManager() {
+		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
+		if(serverProperties.getServlet().getSession().getTimeout()!=null) {
+			//单位毫秒
+			sessionManager.setGlobalSessionTimeout(serverProperties.getServlet().getSession().getTimeout().getSeconds()*1000L);
+		}
+		sessionManager.setSessionDAO(getMemorySessionDAO());
+		sessionManager.setSessionIdCookie(getSimpleCookie());
+		sessionManager.setSessionIdUrlRewritingEnabled(false);
+		return sessionManager;
+	}
+
+	/**
+	 * 身份验证器
+	 * @return Authenticator
+	 */
+	@Bean
+	public Authenticator authenticator() {
+		CustomModularRealmAuthenticator modularRealmAuthenticator = new CustomModularRealmAuthenticator();
+		modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
+		return modularRealmAuthenticator;
+	}
+
+
+	@Bean
+	public MemorySessionDAO getMemorySessionDAO() {
+		return new MemorySessionDAO();
+	}
+
+	@Bean
+	public SimpleCookie getSimpleCookie() {
+		SimpleCookie simpleCookie = new SimpleCookie();
+		simpleCookie.setName(msProperties.getCookieName());
+		return simpleCookie;
+
+	}
+
+
+
+	/**
+	 * 自定义身份认证 realm;
+	 * <p>
+	 * 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm, 否则会影响 CustomRealm类 中其他类的依赖注入
+	 */
+	@Bean
+	public ManagerAuthRealm customRealm() {
+		return new ManagerAuthRealm();
+	}
+
+
+	/**
+	 * 自定义会员身份认证realm,依赖会员后放开202-205行
+	 * @return
+	 */
+//	@Bean("peopleAuth")
+//	public PeopleAuthRealm peopleAuthRealm() {
+//		return new PeopleAuthRealm();
+//	}
+
+	/**
+	 * 管理员菜单策略
+	 *
+	 * @return
+	 */
+	@Bean
+	public IModelStrategy modelStrategy() {
+		return  new ManagerModelStrategy();
+	}
+
+	/**
+	 * 管理登录策略
+	 *
+	 * @return
+	 */
+	@Bean
+	public ILoginStrategy loginStrategy() {
+		return new ManagerLoginStrategy();
+	}
+}