• 【Java从零到架构师第③季】【50】权限控制—Shiro



    持续学习&持续更新中…

    守破离


    权限管理

    在这里插入图片描述

    在这里插入图片描述

    表结构设计

    可以登录后台管理系统的员工/系统管理员:比如:sys_user(表名以sys_开头)

    使用产品的用户/客户(APP、小程序、网页):比如:user

    create table if not exists jk.sys_resource
    (
    	id tinyint unsigned auto_increment comment '主键'
    		primary key,
    	name varchar(15) default '' not null comment '名称',
    	uri varchar(100) default '' not null comment '链接地址',
    	permission varchar(100) default '' not null comment '权限标识',
    	type tinyint unsigned default 0 not null comment '资源类型(0是目录,1是菜单,2是按钮)PS:按钮就是增删改查之类的能点击的',
    	icon varchar(100) default '' not null comment '图标',
    	sn tinyint unsigned default 0 not null comment '序号',
    	parent_id tinyint unsigned default 0 not null comment '父资源id',
    	constraint sys_resource_parent_id_name_uindex
    		unique (parent_id, name)
    )
    comment '资源';
    
    create table if not exists jk.sys_role
    (
    	id tinyint unsigned auto_increment comment '主键'
    		primary key,
    	name varchar(15) default '' not null comment '角色名称',
    	constraint sys_role_name_uindex
    		unique (name)
    )
    comment '角色';
    
    create table if not exists jk.sys_role_resource
    (
    	role_id tinyint unsigned default 0 not null comment '角色id',
    	resource_id tinyint unsigned default 0 not null comment '资源id',
    	primary key (resource_id, role_id)
    )
    comment '角色-资源';
    
    create table if not exists jk.sys_user
    (
    	id smallint unsigned auto_increment comment '主键'
    		primary key,
    	nickname varchar(15) default '' not null comment '昵称',
    	username varchar(15) default '' not null comment '登录用的用户名',
    	password char(32) default '' not null comment '登录用的密码,密码经过MD5加密之后就是32位的字符串',
    	create_time datetime default CURRENT_TIMESTAMP not null comment '创建的时间',
    	login_time datetime null comment '最后一次登录的时间',
    	status tinyint unsigned default 0 not null comment '账号的状态,0是正常,1是锁定',
    	constraint sys_user_username_uindex
    		unique (username)
    )
    comment '用户(可以登录后台系统的)';
    
    create table if not exists jk.sys_user_role
    (
    	role_id tinyint unsigned default 0 not null comment '角色id',
    	user_id smallint unsigned default 0 not null comment '用户id',
    	primary key (user_id, role_id)
    )
    comment '用户-角色';
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    Shiro

    简介

    https://shiro.apache.org/

    https://shiro.apache.org/reference.html

    在这里插入图片描述

    认证、授权

    授权其实就是“鉴权”,鉴定权限

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    HelloWorld

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    pom.xml:

    	<dependency>
    		<groupId>org.apache.shirogroupId>
    		<artifactId>shiro-coreartifactId>
    		<version>1.7.0version>
    	dependency>
    
        <dependency> 
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.2.3version>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    realm.ini:

    [users]
    zhangsan = 123456, admin, normal
    lisi = 123456, normal
    mj = 123456, admin
    lp = lp
    
    [roles]
    admin = user:create, user:read, user:update, user:delete
    normal = user:read
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Main.java:

    private static void testSimple() {
            // 安全管理器:DefaultSecurityManager是SecurityManager的实现类型
            DefaultSecurityManager mgr = new DefaultSecurityManager();
            // 设置安全管理器
            SecurityUtils.setSecurityManager(mgr);
            // 设置Realm
            mgr.setRealm(new IniRealm("classpath:realm.ini"));
    
            // 主体:Subject
            Subject subject = SecurityUtils.getSubject();
    
            // 登录
            String username = "lp";
            String upwd= "lp";
            UsernamePasswordToken token = new UsernamePasswordToken(username, upwd);
    
            try {
                // 未登录之前,查询结构都是false
                // System.out.println("【权限】user:read -> " + subject.isPermitted("user:read"));
                // System.out.println("【权限】user:update -> " + subject.isPermitted("user:update"));
                // System.out.println("【权限】user:delete -> " + subject.isPermitted("user:delete"));
                // System.out.println("【权限】user:create -> " + subject.isPermitted("user:create"));
                // System.out.println("【角色】admin -> " + subject.hasRole("admin"));
                // System.out.println("【角色】normal -> " + subject.hasRole("normal"));
    
                // 判断这个用户(主体)是否已认证成功
                // System.out.println(subject.isAuthenticated());
    
                System.out.println("【登录之前】isAuthenticated -> " + subject.isAuthenticated());
    
                subject.login(token);
    
                System.out.println("【登录之后】isAuthenticated -> " + subject.isAuthenticated());
    
                System.out.println("【权限】user:read -> " + subject.isPermitted("user:read"));
                System.out.println("【权限】user:update -> " + subject.isPermitted("user:update"));
                System.out.println("【权限】user:delete -> " + subject.isPermitted("user:delete"));
                System.out.println("【权限】user:create -> " + subject.isPermitted("user:create"));
                System.out.println("【角色】admin -> " + subject.hasRole("admin"));
                System.out.println("【角色】normal -> " + subject.hasRole("normal"));
    
                // 退出登录
                subject.logout();
    
                System.out.println("【退出登录】isAuthenticated -> " + subject.isAuthenticated());
                System.out.println("【退出登录 权限】user:read -> " + subject.isPermitted("user:read"));
                System.out.println("【退出登录 角色】normal -> " + subject.hasRole("normal"));
    
            } catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
            } catch (IncorrectCredentialsException e) {
                System.out.println("密码不正确");
            } catch (AuthenticationException e) {
                System.out.println("认证失败");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    自定义Realm+Shiro工作原理

    Realm就是数据源

    Model准备:

    @Data
    public class SysUser {
        private String usenrname;
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    // 模拟数据库的查询操作
    public class Dbs {
        public static SysUser get(String username) {
            if ("mj666".equals(username)) {
                SysUser user = new SysUser();
                user.setUsenrname("mj666");
                user.setPassword("mj666");
                return user;
            } else if ("mj333".equals(username)) {
                SysUser user = new SysUser();
                user.setUsenrname("mj333");
                user.setPassword("mj333");
                return user;
            }
            return null;
        }
    
        public static List<String> getRoles(String username) {
            if ("mj666".equals(username)) {
                return List.of("admin");
            } else if ("mj333".equals(username)) {
                return List.of("normal");
            }
            return null;
        }
    
        public static List<String> getPermissions(String username) {
            if ("mj666".equals(username)) {
                return List.of("user:create", "user:update", "user:delete");
            } else  if ("mj333".equals(username)) {
                return List.of("user:read");
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    自定义Realm:CustomRealm.java

    // 授权的前提就是认证通过,因此自定义Realm可以继承自AuthorizingRealm
    // 所以这个CustomRealm既可以进行认证,也可以负责授权
    public class CustomRealm extends AuthorizingRealm {
    
        /**
         * 当主体(subject)要进行权限\角色判断时,就会调用
         *
         * 开发者需要在这个方法中干啥?【一般】
         * 根据用户名查询用户的角色\权限信息
         *
         * @return 用户的角色\权限信息
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String username = (String) principals.getPrimaryPrincipal();
    
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    
            List<String> roles = Dbs.getRoles(username);
            if (roles != null) {
                info.addRoles(roles);
            }
    
            List<String> permissions = Dbs.getPermissions(username);
            if (permissions != null) {
                info.addStringPermissions(permissions);
            }
    
            return info;
        }
    
        /**
         * 当主体(subject)要进行认证时,就会调用
         *
         * 开发者需要在这个方法中干啥?【一般】
         * 根据用户名查询用户的具体信息(用户名、密码、...)
         *
         * @param token subject.login()登录时传进来的token
         * @return 用户的具体信息(用户名、密码)
         */
        // AuthenticationInfo doGetAuthenticationInfo()这个方法只需要根据认证Token返回用户的认证信息即可
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            // 获取token
            UsernamePasswordToken tk = (UsernamePasswordToken) token;
    
            // 根据用户名去数据库中查询用户信息
            String username = (String) tk.getPrincipal();
            SysUser user = Dbs.get(username);
    
            if (user == null) return null;
    
            // 认证成功,直接返回即可
            return new SimpleAuthenticationInfo(user.getUsenrname(), user.getPassword(), getName());
        }
    
    }
    
    //        下面注销的代码(判断认证是否成功/匹配用户的密码)是不用自己做的;具体可以参考其它Realm的实现
    //        if (user == null) {
    //            throw new UnknownAccountException();
    //        }
    //        String upwd = tk.getCredentials().toString();
    //        if (!upwd.equals(user.getPassword())) {
    //            throw new IncorrectCredentialsException();
    //        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    使用:Main.java

    /*
    认证流程:
        1、Subject.login(token)
        2、SecurityManager -> Authenticator -> Realm【AuthorizingRealm】
        3、info = AuthorizingRealm.doGetAuthenticationInfo(token),
          根据token信息查询对应的用户信息(比如去数据库中查找)
        4、CredentialsMatcher.doCredentialsMatch(token, info),
          判断token、info的Credentials是否匹配。
          PS: CredentialsMatcher:专门用来判断Credentials(密码)是否正确
    
    授权(判断权限、角色)流程:
        1、Subject.isPermitted(permission)、Subject.hasRole(role)
        2、SecurityManager -> Authorizer -> Realm【AuthorizingRealm】
        3、info = AuthorizingRealm.doGetAuthorizationInfo(principal的集合),根据principal查询对应的角色、权限信息
        4、根据返回的info信息判断权限、角色是否正确
     */
    
    public class Main {
        public static void main(String[] args) {
            // 安全管理器:DefaultSecurityManager是SecurityManager的实现类型
            DefaultSecurityManager mgr = new DefaultSecurityManager();
            // 使用安全管理器
            SecurityUtils.setSecurityManager(mgr);
            // 设置Realm
            mgr.setRealm(new CustomRealm());
    
            // 主体:Subject
            Subject subject = SecurityUtils.getSubject();
    
            // 登录
            String username = "mj333";
            String upwd = "mj333";
            UsernamePasswordToken token = new UsernamePasswordToken(username, upwd);
    
            try {
                subject.login(token);
    
                System.out.println("【权限】user:read -> " + subject.isPermitted("user:read"));
                System.out.println("【权限】user:update -> " + subject.isPermitted("user:update"));
                System.out.println("【权限】user:delete -> " + subject.isPermitted("user:delete"));
                System.out.println("【权限】user:create -> " + subject.isPermitted("user:create"));
                System.out.println("【角色】admin -> " + subject.hasRole("admin"));
                System.out.println("【角色】normal -> " + subject.hasRole("normal"));
            } catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
            } catch (IncorrectCredentialsException e) {
                System.out.println("密码不正确");
            } catch (AuthenticationException e) {
                System.out.println("认证失败");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    SpringBoot—Shiro

    在这里插入图片描述

    	
    	<dependency>
    	    <groupId>org.apache.shirogroupId>
    	    <artifactId>shiro-spring-boot-web-starterartifactId>
    	    <version>${shiro.version}version>
    	dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    @Configuration
    public class ShiroConfig {
        @Bean
        public Realm realm() {
            return new TokenRealm(new TokenMatcher());
        }
    
        /**
         * ShiroFilterFactoryBean用来告诉Shiro如何进行拦截
         * 1.拦截哪些URL
         * 2.每个URL需要经过哪些filter
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(Realm realm/*, JkProperties properties*/) {
            ShiroFilterFactoryBean filterBean = new ShiroFilterFactoryBean();
    
            // 安全管理器
            filterBean.setSecurityManager(new DefaultWebSecurityManager(realm));
    
            // 添加一些自定义Filter
            Map<String, Filter> filters = new HashMap<>();
            filters.put("token", new TokenFilter());
            filterBean.setFilters(filters);
    
            // 设置URL如何拦截
            // Filter的顺序很重要,因此需要使用LinkedHashMap
            Map<String, String> urlMap = new LinkedHashMap<>();
            // 验证码
            urlMap.put("/sysUsers/captcha", "anon");
            // 用户登录
            urlMap.put("/sysUsers/login", "anon");
            // 全局Filter的异常处理
            urlMap.put(ErrorFilter.ERROR_URI, "anon");
            // 其他
            urlMap.put("/**", "token");
            filterBean.setFilterChainDefinitionMap(urlMap);
    
            return filterBean;
        }
    
        /**
         * 解决:@RequiresPermissions导致控制器接口404
         */
        @Bean
        public DefaultAdvisorAutoProxyCreator proxyCreator() {
            DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
            proxyCreator.setUsePrefix(true);
            return proxyCreator;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    /**
     * 作用:验证用户的合法性、是否有相关权限
     */
    @Slf4j
    public class TokenFilter extends AccessControlFilter {
        public static final String HEADER_TOKEN = "Token";
    
        /**
         * 当请求被TokenFilter拦截时,就会调用这个方法
         * 可以在这个方法中做初步判断
         *
         * 如果返回true:允许访问。可以进入下一个链条调用(比如Filter、拦截器、控制器等)
         * 如果返回false:不允许访问。会进入onAccessDenied方法
         */
        @Override
        protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
    //        // 可以在这个方法中做初步判断,比如放行所有的OPTIONS请求
    //        return "OPTIONS".equals(request.getMethod());
    
            log.debug("TokenFilter - isAccessAllowed - " + request.getRequestURI());
            return false;
        }
    
        /**
         * 当isAccessAllowed返回false时,就会调用这个方法
         * 进一步拦截,比如:在这个方法中进行token的校验
         *
         * 如果返回true:允许访问。可以进入下一个链条调用(比如Filter、拦截器、控制器等)
         * 如果返回false:不允许访问。不会进入下一个链条调用(比如Filter、拦截器、控制器等)
         */
        @Override
        protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            log.debug("TokenFilter - onAccessDenied - " + request.getRequestURI());
    
            // 取出Token
            String token = request.getHeader(HEADER_TOKEN);
    
            // 如果没有Token
            if (token == null) {
                return JSONResults.exception(CodeMsg.NO_TOKEN);
            }
    
            // 如果Token过期了
            if (Caches.getToken(token) == null) {
                return JSONResults.exception(CodeMsg.TOKEN_EXPIRED);
            }
    
            log.debug("TokenFilter - onAccessDenied - " + token);
    
            // 鉴权(进入Realm)
            // 这里调用login,并不是“登录”的意思,是为了触发Realm的相应方法去加载用户的角色、权限信息,
            // 以便鉴权
            SecurityUtils.getSubject().login(new Token(token));
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    @Data
    public class Token implements AuthenticationToken {
        private final String token;
    
        public Token(String token) {
            this.token = token;
        }
    
        @Override
        public Object getPrincipal() {
            return token;
        }
    
        @Override
        public Object getCredentials() {
            return token;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    @Slf4j
    public class TokenMatcher implements CredentialsMatcher {
        @Override
        public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
            log.debug("TokenMatcher - doCredentialsMatch - {} {}", token, info);
            // 不用做匹配密码的判断,我们并不是处理“登录”操作,只是用来《鉴权》
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @Slf4j
    public class TokenRealm extends AuthorizingRealm {
    
        public TokenRealm(TokenMatcher matcher) {
            super(matcher);
        }
    
        @Override
        public boolean supports(AuthenticationToken token) {
            log.debug("TokenRealm - supports - {}", token);
            return token instanceof Token; // 只处理我们自己的Token
        }
    
        // 认证通过才会调用授权方法加载权限信息
        // AuthorizationInfo用来存放用户的权限信息
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            // 拿到当前登录用户的token
            String token = (String) principals.getPrimaryPrincipal();
            log.debug("TokenRealm - doGetAuthorizationInfo - {}", token);
    
            // 根据token查找用户的角色、权限
            // 比如去数据库、缓存中去查找
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    		// 如果你是某个用户(具有某个Token),就给你plateRegions:list这个权限
    //        info.addRole("manager");
    		info.addStringPermission("dictItem:list");
    
            return info;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
                throws AuthenticationException {
            String tk = ((Token) token).getToken();
            log.debug("TokenRealm - doGetAuthenticationInfo - {}", tk);
            return new SimpleAuthenticationInfo(tk, tk, getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    public class Constants {
       	// ...
    
        public static class Permisson {
            public static final String SYS_USER_LIST = "sysUser:list";
            public static final String SYS_USER_ADD = "sysUser:add";
            public static final String SYS_USER_UPDATE = "sysUser:update";
            public static final String SYS_USER_REMOVE = "sysUser:remove";
    
            public static final String SYS_ROLE_LIST = "sysRole:list";
            public static final String SYS_ROLE_ADD = "sysRole:add";
            public static final String SYS_ROLE_UPDATE = "sysRole:update";
            public static final String SYS_ROLE_REMOVE = "sysRole:remove";
    
            public static final String SYS_RESOURCE_LIST = "sysResource:list";
            public static final String SYS_RESOURCE_ADD = "sysResource:add";
            public static final String SYS_RESOURCE_UPDATE = "sysResource:update";
            public static final String SYS_RESOURCE_REMOVE = "sysResource:remove";
    
            public static final String DICT_ITEM_LIST = "dictItem:list";
            public static final String DICT_ITEM_ADD = "dictItem:add";
            public static final String DICT_ITEM_UPDATE = "dictItem:update";
            public static final String DICT_ITEM_REMOVE = "dictItem:remove";
    
            public static final String DICT_TYPE_LIST = "dictType:list";
            public static final String DICT_TYPE_ADD = "dictType:add";
            public static final String DICT_TYPE_UPDATE = "dictType:update";
            public static final String DICT_TYPE_REMOVE = "dictType:remove";
    
            public static final String EXAM_PLACE_LIST = "examPlace:list";
            public static final String EXAM_PLACE_ADD = "examPlace:add";
            public static final String EXAM_PLACE_UPDATE = "examPlace:update";
            public static final String EXAM_PLACE_REMOVE = "examPlace:remove";
    
            public static final String EXAM_PLACE_COURSE_LIST = "examPlaceCourse:list";
            public static final String EXAM_PLACE_COURSE_ADD = "examPlaceCourse:add";
            public static final String EXAM_PLACE_COURSE_UPDATE = "examPlaceCourse:update";
            public static final String EXAM_PLACE_COURSE_REMOVE = "examPlaceCourse:remove";
    
            public static final String PROVINCE_LIST = "province:list";
            public static final String PROVINCE_ADD = "province:add";
            public static final String PROVINCE_UPDATE = "province:update";
            public static final String PROVINCE_REMOVE = "province:remove";
    
            public static final String CITY_LIST = "city:list";
            public static final String CITY_ADD = "city:add";
            public static final String CITY_UPDATE = "city:update";
            public static final String CITY_REMOVE = "city:remove";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    @RestController
    @RequestMapping("/dictItems")
    @Api(tags = "数据字典条目", description = "DictItem")
    public class DictItemController extends BaseController<DictItem, ReqSaveDictItem> {
        @Autowired
        private DictItemService service;
    
        @GetMapping
        @ApiOperation("分页查询")
        @RequiresPermissions(Constants.Permisson.DICT_ITEM_LIST)
        public JSONPageResult<RespDictItem> list(@Valid ReqPageDictItem reqPageDictItem) {
            return service.list(reqPageDictItem);
        }
    
        @Override
        @RequiresPermissions(value = {
                Constants.Permisson.DICT_ITEM_ADD,
                Constants.Permisson.DICT_ITEM_UPDATE
        }, logical = Logical.AND)
        public JSONResult save(ReqSaveDictItem entity) {
            return super.save(entity);
        }
    
        @Override
        // @RequiresRoles({"admin"})
        @RequiresPermissions(Constants.Permisson.DICT_ITEM_REMOVE)
        public JSONResult remove(String id) {
            return super.remove(id);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    参考

    小码哥-李明杰: Java从0到架构师③进阶互联网架构师.


    本文完,感谢您的关注支持!


  • 相关阅读:
    不用开会员就能在线编辑、管理及分享各类地理空间数据!
    还在付费使用 XShell?我选择这款超牛逼的 SSH 客户端,完全免费
    线上线下结合的经营方式 同城服务平台搭建
    文本表示(Representation)
    C语言学习(十一)之字符输入/输出
    C#中DataAdapter对象
    sqlite3数据库文件损坏修复
    3、TCP状态
    硬盘的简单介绍
    一篇文章让你入门【MySQL】
  • 原文地址:https://blog.csdn.net/weixin_44018671/article/details/125890361