| | |
| | | import org.springframework.boot.SpringApplication; |
| | | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| | | import org.springframework.boot.web.servlet.ServletComponentScan; |
| | | import org.springframework.cache.annotation.EnableCaching; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.ComponentScan; |
| | | import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
| | | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; |
| | | import org.springframework.web.servlet.view.InternalResourceViewResolver; |
| | | |
| | | /** |
| | | * @Description : 启动类 |
| | |
| | | @SpringBootApplication |
| | | @EnableWebMvc |
| | | @ServletComponentScan(basePackages = {"com.whyc.filter","com.whyc.servlet"}) |
| | | @EnableCaching |
| | | public class Application extends WebMvcConfigurerAdapter implements WebMvcConfigurer { |
| | | |
| | | public static void main(String[] args) { |
| | |
| | | @ConditionalOnProperty(name = "redis.model", havingValue = "single") |
| | | @Order(1) |
| | | RedissonClient redissonClientSingle() { |
| | | log.error("redis单机版client初始化了"); |
| | | log.error("redis single client初始化了"); |
| | | Config config = new Config(); |
| | | String node = redisProperties.getSingle().getAddress(); |
| | | SingleServerConfig serverConfig = config.useSingleServer() |
| | |
| | | @Bean("redisClient") |
| | | @ConditionalOnProperty(name = "redis.model", havingValue = "sentinel") |
| | | RedissonClient redissonClientSentinel() { |
| | | log.error("redis单机版client初始化了"); |
| | | log.error("redis sentinel client初始化了"); |
| | | Config config = new Config(); |
| | | |
| | | String[] nodes = redisProperties.getSentinel().getNodes().split(","); |
| | |
| | | @Bean("redisClient") |
| | | @ConditionalOnProperty(name = "redis.model", havingValue = "cluster") |
| | | RedissonClient redissonClientCluster() { |
| | | log.error("redis单机版client初始化了"); |
| | | log.error("redis cluster client初始化了"); |
| | | Config config = new Config(); |
| | | RedisClusterProperties cluster = redisProperties.getCluster(); |
| | | RedisPoolProperties pool = redisProperties.getPool(); |
| | |
| | | return Redisson.create(config); |
| | | } |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | @Bean("redisClient") |
| | | @ConditionalOnProperty(name = "redis.model", havingValue = "master-slave") |
| | | RedissonClient redissonClientMasterSlave() { |
| | | log.error("redis master-slave client初始化了"); |
| | | Config config = new Config(); |
| | | RedisClusterProperties cluster = redisProperties.getCluster(); |
| | | RedisPoolProperties pool = redisProperties.getPool(); |
| | | String[] nodes = cluster.getNodes().split(","); |
| | | MasterSlaveServersConfig serversConfig = config.useMasterSlaveServers() |
| | | .setMasterAddress(nodes[0]) |
| | | .addSlaveAddress(nodes[1]); |
| | | |
| | | if (!StringUtils.isEmpty(redisProperties.getPassword())) { |
| | | serversConfig.setPassword(redisProperties.getPassword()); |
| | | } |
| | | return Redisson.create(config); |
| | | } |
| | | |
| | | } |
| | |
| | | import org.apache.shiro.session.Session; |
| | | import org.apache.shiro.session.UnknownSessionException; |
| | | import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; |
| | | import org.redisson.Redisson; |
| | | import org.redisson.api.RBucket; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.redisson.config.Config; |
| | | import org.redisson.config.SingleServerConfig; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; |
| | | import org.springframework.context.annotation.DependsOn; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.Serializable; |
| | |
| | | */ |
| | | @Slf4j |
| | | public class RedisSessionDao extends AbstractSessionDAO { |
| | | |
| | | /*@Resource(name = "redissonClient4Shiro") |
| | | RedissonClient redissonClient;*/ |
| | | |
| | | @Autowired |
| | | RedissonClient redissonClient; |
| | |
| | | |
| | | //将Session存入redis |
| | | RBucket<String> sessionIdBucket = redissonClient.getBucket(SuperConstant.GROUP_CAS + sessionId.toString()); |
| | | sessionIdBucket.trySet(ShiroRedissionSerialize.serialize(session),globalSessionTimeout, TimeUnit.SECONDS); |
| | | sessionIdBucket.trySet(ShiroRedissionSerialize.serialize(session),globalSessionTimeout, TimeUnit.MILLISECONDS); |
| | | log.info("session创建:SessionId:{}",session.getId().toString()); |
| | | return sessionId; |
| | | } |
| | | |
| | |
| | | package com.whyc.config; |
| | | |
| | | import com.whyc.filter.KickedOutFilter; |
| | | import com.whyc.filter.RolesOrAuthorizationFilter; |
| | | import com.whyc.properties.PropertiesUtil; |
| | | import com.whyc.properties.RedisProperties; |
| | | import com.whyc.properties.ShiroRedisProperties; |
| | | import com.whyc.realm.CustomRealm; |
| | | import lombok.extern.log4j.Log4j; |
| | | import lombok.extern.log4j.Log4j2; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.shiro.session.mgt.SessionManager; |
| | | import org.apache.shiro.session.mgt.eis.SessionDAO; |
| | | import org.apache.shiro.spring.LifecycleBeanPostProcessor; |
| | | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; |
| | | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; |
| | | import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter; |
| | | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; |
| | | import org.apache.shiro.web.servlet.SimpleCookie; |
| | | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; |
| | | import org.redisson.Redisson; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.redisson.config.Config; |
| | | import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.ComponentScan; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.context.annotation.DependsOn; |
| | | |
| | | import javax.servlet.Filter; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 暂时提供权限管理,会话管理后续更新 TODO |
| | | * 暂时提供权限管理,会话管理后续更新 |
| | | */ |
| | | @Configuration |
| | | @Slf4j |
| | |
| | | sessionManager.setSessionDAO(redisSessionDao()); |
| | | sessionManager.setSessionValidationSchedulerEnabled(false); |
| | | sessionManager.setSessionIdCookieEnabled(true); |
| | | sessionManager.setSessionIdUrlRewritingEnabled(false); |
| | | |
| | | SimpleCookie simpleCookie = new SimpleCookie("ShiroSession"); |
| | | SimpleCookie simpleCookie = new SimpleCookie("CT"); |
| | | sessionManager.setSessionIdCookie(simpleCookie); |
| | | sessionManager.setGlobalSessionTimeout(redisProperties.getGlobalSessionTimeout()); |
| | | return sessionManager; |
| | |
| | | return map; |
| | | } |
| | | |
| | | /**自定义过滤器*/ |
| | | private Map<String, Filter> filters(){ |
| | | HashMap<String, Filter> map = new HashMap<>(); |
| | | map.put("rolesOr",new RolesOrAuthorizationFilter()); |
| | | return map; |
| | | } |
| | | |
| | | /**过滤器*/ |
| | | // @Bean("shiroFilter") |
| | | @Bean |
| | | public ShiroFilterFactoryBean shiroFilterFactoryBean(){ |
| | | ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); |
| | | //注入新定义的过滤器 |
| | | shiroFilter.setFilters(filters()); |
| | | //shiroFilter |
| | | shiroFilter.setSecurityManager(defaultWebSecurityManager()); |
| | | shiroFilter.setFilterChainDefinitionMap(filterChainDefinition()); |
| | | shiroFilter.setLoginUrl("/login.html"); |
| | | shiroFilter.setLoginUrl("/index.html"); |
| | | //shiroFilter.setLoginUrl("/index.html#login"); |
| | | shiroFilter.setUnauthorizedUrl("/login/unauthorized"); |
| | | return shiroFilter; |
| | |
| | | |
| | | @Override |
| | | public void addResourceHandlers(ResourceHandlerRegistry registry) { |
| | | |
| | | //这个是可行的,解析的时候path为*.html,校验路径admin下是否存在 |
| | | registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/"); |
| | | /*//这个是可行的,解析的时候path为*.html,校验路径admin下是否存在 |
| | | //registry.addResourceHandler("admin/*.html").addResourceLocations("classpath:/META-INF/resources/admin/"); |
| | | registry.addResourceHandler("/map/*").addResourceLocations("classpath:/META-INF/resources/map/"); |
| | | |
| | | //registry.addResourceHandler("/login.html").addResourceLocations("classpath:/META-INF/resources/"); |
| | | registry.addResourceHandler("*.html").addResourceLocations("classpath:/META-INF/resources/"); |
| | | registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); |
| | | registry.addResourceHandler("/service-worker.js").addResourceLocations("classpath:/META-INF/resources/"); |
| | | registry.addResourceHandler("/service-worker.js").addResourceLocations("classpath:/META-INF/resources/");*/ |
| | | //registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/"); |
| | | super.addResourceHandlers(registry); |
| | | //registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); |
| | |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.cache.annotation.CacheEvict; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | |
| | | |
| | | @PostMapping("bindingUserWithRole") |
| | | @ApiOperation(value = "绑定用户和角色") |
| | | @CacheEvict(cacheNames = {"userBridge"},key="'getAuthorizationInfo'+#p0") //清除 |
| | | public boolean bindingUserWithRole(@RequestParam int userId,int roleId){ |
| | | return userRoleService.bindingUserWithRole(userId,roleId); |
| | | } |
| | | |
| | | @PostMapping("bindingUserWithRoleBatch") |
| | | @ApiOperation(value = "批量绑定用户和角色",notes = "传入userId和roleId的数组") |
| | | @CacheEvict(cacheNames = {"userBridge"},allEntries = true) //全部清除 |
| | | public boolean bindingUserWithRoleBatch(@RequestBody List<UserRole> userRoles){ |
| | | return userRoleService.bindingUserWithRoleBatch(userRoles); |
| | | } |
| | |
| | | |
| | | @PostMapping("bindingRoleWithPermission") |
| | | @ApiOperation(value = "绑定角色-权限") |
| | | @CacheEvict(cacheNames = {"userBridge"},allEntries = true) //全部清除 |
| | | public boolean bindingRoleWithPermission(@RequestParam int roleId,int permissionId){ |
| | | return rolePermissionService.bindingUserWithRole(roleId,permissionId); |
| | | } |
| | | |
| | | @PostMapping("bindingRoleWithPermissionBatch") |
| | | @ApiOperation(value = "批量绑定角色-权限",notes = "传入roleId和privilegeId的数组") |
| | | @CacheEvict(cacheNames = {"userBridge"},allEntries = true) //全部清除 |
| | | public boolean bindingRoleWithPermissionBatch(@RequestBody List<RolePermission> rolePermissions){ |
| | | return rolePermissionService.bindingUserWithRoleBatch(rolePermissions); |
| | | } |
| | |
| | | // String origin = "http://localhost:8080"; |
| | | resp.setHeader("Access-Control-Allow-Origin", origin); |
| | | resp.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type,token"); |
| | | resp.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH"); |
| | | resp.setHeader("Access-Control-Allow-Methods", "GET, POST,TRACE, OPTIONS, PATCH"); |
| | | resp.setHeader("Access-Control-Allow-Credentials", "true"); |
| | | |
| | | chain.doFilter(request, resp); |
| | |
| | | * 用户菜单 |
| | | */ |
| | | @Alias("Menu") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "`tb_menu`") |
| | | @TableName( schema = "`db_cluster_test`",value = "`tb_menu`") |
| | | public class Menu { |
| | | private Integer id; |
| | | private String name; |
| | |
| | | * 权限 |
| | | */ |
| | | @Alias("Permission") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "tb_permission") |
| | | @TableName( schema = "`db_cluster_test`",value = "tb_permission") |
| | | public class Permission { |
| | | |
| | | private Integer id; |
| | |
| | | * 角色 |
| | | */ |
| | | @Alias("Role") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "tb_role") |
| | | @TableName( schema = "`db_cluster_test`",value = "tb_role") |
| | | public class Role { |
| | | private Integer id; |
| | | @TableField("name") |
| | |
| | | * 角色菜单 |
| | | */ |
| | | @Alias("RoleMenu") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "tb_role_menu") |
| | | @TableName( schema = "`db_cluster_test`",value = "tb_role_menu") |
| | | public class RoleMenu { |
| | | private Integer id; |
| | | private Integer roleId; |
| | |
| | | * 角色对应权限 |
| | | */ |
| | | @Alias("RolePrivilege") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "tb_role_privilege") |
| | | @TableName( schema = "`db_cluster_test`",value = "tb_role_privilege") |
| | | public class RolePermission { |
| | | |
| | | private Integer id; |
| | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | @Alias("User") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "tb_user") |
| | | @TableName( schema = "`db_cluster_test`",value = "tb_user") |
| | | public class User implements Serializable { |
| | | private Integer id; |
| | | private String name; |
| | |
| | | * 用户角色表 |
| | | */ |
| | | @Alias("UserRole") |
| | | @TableName( schema = "`db_3.5mw_web`",value = "tb_user_role") |
| | | @TableName( schema = "`db_cluster_test`",value = "tb_user_role") |
| | | public class UserRole { |
| | | |
| | | private Integer id; |
| | |
| | | package com.whyc.properties; |
| | | |
| | | import lombok.extern.log4j.Log4j2; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | /** |
| | | * @Description 读取Properties的工具类 |
| | |
| | | }*/ |
| | | try { |
| | | propertiesShiro.load(PropertiesUtil.class.getClassLoader() |
| | | .getResourceAsStream("config/authentication.properties")); |
| | | .getResourceAsStream("config/authentication.properties.bak")); |
| | | } catch (Exception e) { |
| | | log.warn("资源路径中不存在authentication.properties权限文件,忽略读取!"); |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.whyc.mapper.*; |
| | | import com.whyc.pojo.Permission; |
| | | import com.whyc.mapper.RolePermissionMapper; |
| | | import com.whyc.mapper.UserMapper; |
| | | import com.whyc.mapper.UserRoleMapper; |
| | | import com.whyc.pojo.User; |
| | | import org.apache.shiro.authz.AuthorizationInfo; |
| | | import org.apache.shiro.authz.SimpleAuthorizationInfo; |
| | | import org.springframework.cache.annotation.CacheConfig; |
| | | import org.springframework.cache.annotation.Cacheable; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 处理 shiro认证,授权,和数据库交互 |
| | | */ |
| | | @Service |
| | | //Unified Naming |
| | | @CacheConfig(cacheNames ={"userBridge"}) |
| | | public class UserBridgeService { |
| | | |
| | | @Resource |
| | |
| | | public User findPasswordAndSlatByUserName(String userName) { |
| | | QueryWrapper<User> queryWrapper = Wrappers.query(); |
| | | queryWrapper.select("id","name","password","salt").eq("name",userName); |
| | | try{ |
| | | return userMapper.selectOne(queryWrapper); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | return new User(0,"用户不存在"); |
| | | } |
| | | return userMapper.selectOne(queryWrapper); |
| | | |
| | | } |
| | | |
| | | @Cacheable(key = "#root.methodName+#p0.id") |
| | | public AuthorizationInfo getAuthorizationInfo(User user) { |
| | | System.out.println("=========执行了UserBridgeService.getAuthorization方法=========="); |
| | | SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); |
| | |
| | | return authorizationInfo; |
| | | } |
| | | |
| | | //@Cacheable(key = "#root.methodName+#userId") |
| | | private List<String> findPermissionsByUserId(int userId) { |
| | | List<String> perms = rolePermissionMapper.findPermissionsByUserId(userId); |
| | | return perms; |
| | | } |
| | | |
| | | //@Cacheable(key="#root.methodName+#userId") |
| | | private List<String> findRolesByUserId(int userId) { |
| | | List<String> roles =userRoleMapper.findRolesByUserId(userId); |
| | | //roles.add("dev"); |
| | |
| | | public Response add(User user) { |
| | | try { |
| | | User userFound = userBridgeService.findPasswordAndSlatByUserName(user.getName()); |
| | | if (userFound.getId() != 0) { |
| | | if (userFound != null) { |
| | | return new Response<>().set(1, false, "用户已存在"); |
| | | } |
| | | user.setCreateTime(new Date()); |
| | |
| | | #服务端口号 |
| | | server: |
| | | port: 8090 |
| | | # servlet: |
| | | # context-path: /motor |
| | | servlet: |
| | | context-path: /ct |
| | | |
| | | #数据库 |
| | | spring: |
| | | datasource: |
| | | type: com.alibaba.druid.pool.DruidDataSource |
| | | driver-class-name: com.mysql.cj.jdbc.Driver |
| | | url: jdbc:mysql://localhost:3360/db_3.5mw_web?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true |
| | | url: jdbc:mysql://localhost:3360/db_cluster_test?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&useSSL=false |
| | | # url: jdbc:mysql://192.168.10.221:3360/db_3.5mw_web?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true |
| | | # url: jdbc:mysql://192.168.10.221:3360?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true |
| | | # url: jdbc:mysql://192.168.10.222:3360/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true |
| | |
| | | # base-package: com.whyc.controller |
| | | knife: |
| | | enable: true |
| | | # enable: fase |
| | | redis: |
| | | #模式 single/sentinel/cluster |
| | | #模式 single/sentinel/cluster/master-slave |
| | | model: single |
| | | timeout: 3000 |
| | | global-session-timeout: 360000 |
| | | global-session-timeout: 3000 |
| | | password: |
| | | #连接池配置 |
| | | pool: |
| | |
| | | #集群配置 |
| | | cluster: |
| | | scan-interval: 1000 |
| | | nodes: redis://localhost:6379 |
| | | nodes: redis://localhost:6379,redis://localhost:6380 |
| | | read-mode: SLAVE |
| | | retry-attempts: 3 |
| | | failed-attempts: 3 |
| | | slave-connection-pool-size: 64 |
| | | master-connection-pool-size: 64 |
| | | retry-interval: 1500 |
| | | #集群配置 |
| | | master-slave: |
| | | scan-interval: 1000 |
| | | nodes: redis://localhost:6379,redis://localhost:6380 |
| | | |
New file |
| | |
| | | #dev接口调试时使用 |
| | | /**=anon |
| | | |
| | | #静态资源不拦截 |
| | | #/static/**=anon |
| | | ##登录链接不拦截 |
| | | #/login.html=anon |
| | | #/login/**=anon |
| | | #/index.html=anon |
| | | ##接口文档相关不拦截 |
| | | #/doc.html=anon |
| | | #/webjars/**=anon |
| | | #/swagger-resources=anon |
| | | #/swagger-resources/**=anon |
| | | #/v2/api-docs-ext=anon |
| | | #/v2/api-docs=anon |
| | | |
| | | #访问/resource/**需要有admin的角色 |
| | | #/resource/**=roles-or[dev,SuperAdmin] |
| | | |
| | | #设置需要permission的拦截 |
| | | #/WaterComm/**=perms["water:all"] |
| | | #设置RolesOr拦截 |
| | | #/WaterComm/**=rolesOr["admin","dev"] |
| | | |
| | | #其他链接是需要登录的 |
| | | #/**=authc |