【权限管理框架】一文看懂Shiro权限管理框架!2

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 【权限管理框架】一文看懂Shiro权限管理框架!

6.Shiro权限认证Web案例

6.1.Shiro内置的过滤器

  • 核心过滤器类:DefaultFilter,配置那个路径对应那个拦截器进行处理
authc:org.apache.shiro.web.filter.authc.FromAuthenticationFilter
- 需要认证登录才能访问
user:org.apache.shiro.web.filter.authc.UserFilter
- 用户拦截器,表示必须存在用户
anon:org.apache.shiro.web.filter.authc.AnonymousFilter
- 匿名拦截器,不需要登录即可访问的资源,匿名用户或者游客,一般用于过滤静态资源
roles:org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
- 角色授权拦截器,验证用户是否拥有角色。
- 参数可以写多个,多个参数时写roles["admin","user"],当多个参数时必须每个参数都通过才算通过。
perms:org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
- 权限授权拦截器,验证用户是否拥有权限
- 参数可写多个,和角色多个是一致的
authcBasic:org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
- httpBasic身份验证拦截器
logout:org.apache.shiro.web.filter.authc.LogoutFilter
- 退出拦截器,执行后会执行跳转到shiroFilterFactoryBean.setLoginUrl()设置的url
port:org.apache.shiro.web.filter.authz.PortFilter
- 端口拦截器,可通过的端口
ssl:org.apache.shiro.web.filter.authz.SslFilter
- ssl拦截器,只有请求协议是https才能通过

6.2.Shiro的Filter配置路径

  • 路径支持通配符,完整匹配,注意匹配符不包括分隔符"/"
  • 路径通配符支持?、*、**,注意通配符匹配不包括目录分隔符"/"
  • * 可以匹配所有。不加 * 可以进行前缀匹配,但多个冒号就需要多个 * 来匹配
URL权限采取第一次匹配优先的方式,优先匹配靠前的规则
?:匹配一个字符,如/user? 匹配/user3,但不匹配/user/
*:匹配0个或多个字符串,如/add*,匹配/addtest,但不匹配/add/1
** : 匹配路径中的零个或多个路径,如 /user/** 将匹 配 /user/xxx 或 /user/xxx/yyy
例子
/user/**=filter1
/user/add=filter2
请求 /user/add  命中的是filter1拦截器
  • 性能问题:通配符比字符串匹配会复杂点,所以性能也会稍弱,推荐使用字符匹配方式

6.3.Shiro数据安全之数据加解密

(1)为啥要加解密

  • 明文数据容易泄露,比如密码铭文存储,万一泄露则会造成严重的后果

(2)什么是散列算法

  • 一般叫hash,简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数,适合存储密码,比如MD5
  • (3)什么是salt(盐)
  • 如果直接通过散列函数得到的加密数据,容易被对应解密网站暴力破解,一般会在应用层序里面加特殊的自动进行处理,比如用户id等等,唯一标识的东西。

4)Shiro里面CredentialsMatcher,用来验证密码是否正确

源码:AuthenticatingRealm -> assertCredentialsMatch()


c987801da8c1415dae091dbaecd8678e.jpg

(5)自定义验证规则

一般会自定义验证规则
  @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //散列算法,使用MD5算法;
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //散列的次数,比如散列两次,相当于 md5(md5("xxx"));
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

6.4.Shiro权限控制注解

@RequiresRoles(value={"admin","editor"},logical=Logical.AND)
需要角色admin和editor两个角色同时满足
@RequiresRoles(value={"admin","editor"},logical=Logical.OR)
需要角色admin或editor两个角色其中一个满足
@RequiresAuthentication
已经授过权,调用Subject.isAuthenticated()返回true
@RequiresUser
身份验证或者通过记 住我登录的

查用API

subject.hasRole("xxx")
subject.isPermitted("xxx")
subject.isPermittedAll("xxx","xxx")
subject.checkRole("xxx")

6.5.Shiro缓存模块讲解

  • AuthenticatingRealm 及 AuthorizingRealm 分别提供了对AuthenticationInfo 和 AuthorizationInfo 信息的缓存.

e5f77df325494e5d82909b46eeff2a52.jpg


424460eaae2044f6bccd67f13b7a94cf.jpg

6.6.Shiro Session模块讲解

(1)什么是session会话

用户和程序直接的链接,程序可以根据session识别到哪个用户,和javaweb中的session类似

(2)什么是会话管理器SessionManager

  • 会话管理器管理所有subject的所有操作,是shiro的核心组件
  • 核心方法
//开启一个session
Session start(SessionContext context)
//指定key获取session
Session getSession(SessionKey key)

(3)SessionDao会话存储/持久化

  • SessionDAO
  • AbstractSessionDAO
  • CachingSessionDAO
  • EnterpeiseCacheSessionDAO
  • MemorySessionDAO
  • 核心方法
//创建
Serializable create(Session session)
//获取
Session readSession(Serializable sessionId) throws UnknownSessionException
//更新
void update(Session session)
//删除,会话过期时调用
void delete(Session session)
//获取活跃的session
Collection<Session> getActiveSessions()
RememberMe
1.Cookie写到客户端并保存
2.通过调用subject.login()前,设置 token.setRememberMe(true)
- subject.isAuthenticated() 表示用户进行了身份验证登录的,即Subject.login 进行了登录
- subject.isRemembered() 表示用户是通过RememberMe登录的
- subject.isAuthenticated()==true,则 subject.isRemembered()==false, 两个互斥
- 总结:特殊页面或者API调用才需要authc进行验证拦截,该拦截器会判断用户是否是通过

7.SpringBoot2.x整合Shiro

7.1.数据库设计


6d634cd6444c4bc882610a03e0914207.jpg

  • user表
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(128) DEFAULT NULL COMMENT '用户名',
  `password` varchar(256) DEFAULT NULL COMMENT '密码',
  `create_time` datetime DEFAULT NULL,
  `salt` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
  • role表
CREATE TABLE `role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) DEFAULT NULL COMMENT '名称',
  `description` varchar(64) DEFAULT NULL COMMENT '描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
  • user_role表
CREATE TABLE `user_role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `role_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `remarks` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
  • permission表
CREATE TABLE `permission` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) DEFAULT NULL COMMENT '名称',
  `url` varchar(128) DEFAULT NULL COMMENT '接口路径',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
  • role_permission表
CREATE TABLE `role_permission` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `role_id` int(11) DEFAULT NULL,
  `permission_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

7.2.Maven项目搭建

创建SpringBoot项目,引入依赖,配置数据库

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--阿里巴巴druid数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <!--spring整合shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </pluginRepository>
    </pluginRepositories>
#==============================数据库相关配置========================================
spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.10.88:3306/rbac_shiro?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username =root
spring.datasource.password =123456
#使用阿里巴巴druid数据源,默认使用自带的
#spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
#开启控制台打印sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis 下划线转驼峰配置,两者都可以
#mybatis.configuration.mapUnderscoreToCamelCase=true
mybatis.configuration.map-underscore-to-camel-case=true

7.3.编写查询用户全部信息接口

(1)实体类编写

  • User
/**
 * 用户表
 */
public class User {
    private int id;
    private String username;
    private Date createTime;
    private String salt;
    private List<Role> roleList;
}
  • Role
/**
 * 角色表
 */
public class Role {
    private int id;
    private String name;
    private String description;
    private List<Permission> permissionList;
}
  • UserRole
/**
 * 用户角色中间表
 */
public class UserRole {
    private int id;
    private int userId;
    private int roleId;
}
  • Permission
/**
 * 权限表
 */
public class Permission {
    private int id;
    private String name;
    private String url;
}
  • RolePermission
/**
 * 权限角色中间表
 */
public class RolePermission {
    private int id;
    private int roleId;
    private int permissionId;
}

(2)Mapper编写

  • UserMapper
public interface UserMapper {
    @Select("select * from user where username = #{username}")
    User findByUsername(@Param("username") String username);
    @Select("select * from user where id = #{id}")
    User findById(@Param("id") int id);
    @Select("select * from user where username = #{username} and password = #{pwd}")
    User findByUsernameAndPwd(@Param("username") String username,@Param("pwd") String pwd);
}
  • RoleMapper
public interface RoleMapper {
    @Select("select * from user_role where user_id = #{userId}")
    List<UserRole> findRolesByUserId(@Param("userId") int userId);
    @Select("select * from role where id = #{roleId}")
    List<Role> findRolesByRoleId(@Param("roleId") int roleId);
}
  • PermissionMapper
public interface PermissionMapper {
    @Select("select * from permission where id = #{roleId}")
    List<Permission> findPermissionsByRoleId(@Param("roleId") int roleId);
}

(3)UserService编写

  • UserService
public interface UserService {
    /**
     * 获取用户全部信息,包括角色权限
     * @param username
     * @return
     */
    User findAllUserInfoByUsername(String username);
    /**
     * 获取用户基本信息
     * @param userId
     * @return
     */
    User findSimpleUserInfoById(int userId);
    /**
     * 获取用户基本信息
     * @param username
     * @return
     */
    User findSimpleUserInfoByUsername(String username);
}
  • UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Override
    public User findAllUserInfoByUsername(String username) {
        User user = userMapper.findByUsername(username);
        List<UserRole> userRoles = roleMapper.findRolesByUserId(user.getId());
        List<Role> roles = new ArrayList<>();
        for (UserRole role : userRoles) {
            roles = roleMapper.findRolesByRoleId(role.getRoleId());
            for (Role x : roles) {
                x.setPermissionList(permissionMapper.findPermissionsByRoleId(x.getId()));
            }
        }
        user.setRoleList(roles);
        return user;
    }
    @Override
    public User findSimpleUserInfoById(int userId) {
        return userMapper.findById(userId);
    }
    @Override
    public User findSimpleUserInfoByUsername(String username) {
        return userMapper.findByUsername(username);
    }
}

(5)controller编写

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/find_user")
    public Object findUserInfo(@RequestParam("username") String username){
        return userService.findAllUserInfoByUsername(username);
    }
}

(6)测试



d24a6b42868c4ff1866c3f8349628bfa.jpg

7.4.开发自定义CustomRealm

  • 继承 AuthorizingRealm
  • 重写 doGetAuthorizationInfo
  • 重写 doGetAuthenticationInfo
public class CustomRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    /**
     * 用户鉴权的时候会调用
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("鉴权 doGetAuthorizationInfo");
        String username = (String)principals.getPrimaryPrincipal();
        User userInfo = userService.findAllUserInfoByUsername(username);
        //将角色,权限放到对应的两个String类型集合中
        List<String> stringRoleList = new ArrayList<>();
        List<String> stringPermissionList = new ArrayList<>();
        List<Role> roleList = userInfo.getRoleList();
        for (Role role : roleList) {
            stringRoleList.add(role.getName());
            List<Permission> permissionList = role.getPermissionList();
            for (Permission permission : permissionList) {
                if(permission!=null){
                    stringPermissionList.add(permission.getName());
                }
            }
        }
        //拿到对应的角色集合,权限集合,封装SimpleAuthorizationInfo对象添加
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(stringRoleList);
        simpleAuthorizationInfo.addStringPermissions(stringPermissionList);
        return simpleAuthorizationInfo;
    }
    /**
     * 用户认证登录的时候会调用
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证 doGetAuthenticationInfo");
        //从token中拿到username
        String username = (String)token.getPrincipal();
        User userInfo = userService.findAllUserInfoByUsername(username);
        //获取密码
        String password = userInfo.getPassword();
        if(password == null || "".equals(password)){
            return null;
        }
        //密码不为空,说明认证成功,封装SimpleAuthenticationInfo对象,参数:用户名,密码,class.getName
        return new SimpleAuthenticationInfo(username,userInfo.getUsername(),this.getClass().getName());
    }
}

7.5.ShiroFilterFactoryBean配置

  • shiroFilterFactoryBean-》
  • SecurityManager-》
  • CustomSessionManager
  • CustomRealm-》hashedCredentialsMatcher
  • SessionManager
  • DefaultSessionManager: 默认实现,常用于javase
  • ServletContainerSessionManager: web环境
  • DefaultWebSessionManager:常用于自定义实现
@Configuration
public class ShiroConfig {
    /**
     * 设置shiroFilter
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        System.out.println("执行 ShiroFilterFactoryBean.shiroFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //设置登录成功后访问的路径
        shiroFilterFactoryBean.setLoginUrl("/pub/need_login");
        //设置登录成功后访问的url
        shiroFilterFactoryBean.setSuccessUrl("/");
        //设置无权限访问的接口,未授权无法访问接口
        shiroFilterFactoryBean.setUnauthorizedUrl("/pub/not_permit");
        //拦截器路径配置,注意这里一定要用LinkedHashMap,HashMap会出现偶尔无法拦截的情况
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        //设置过滤器
        //登出过滤器,用户退出时调用
        filterChainDefinitionMap.put("/logout","logout");
        //匿名过滤器,游客模式
        filterChainDefinitionMap.put("/pub/**","anon");
        //登录过滤器,用户只有登录才能访问
        filterChainDefinitionMap.put("/authc/**","authc");
        //管理员角色才能访问
        filterChainDefinitionMap.put("/admin/**","roles[admin]");
        //指定权限才能访问
        filterChainDefinitionMap.put("/video/update","perms[video_update]");
        filterChainDefinitionMap.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    /**
     * 注入securityManager,设置Realm和SessionManager
     * @return
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        securityManager.setRealm(customRealm());
    //注意如果不是前后端分离的项目就不需要设置sessionManager
        securityManager.setSessionManager(customSessionManager());
        return securityManager;
    }
    /**
     * 设置散列算法
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设设置散列算法,md5
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //设置散列次数
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }
    /**
     * 注入自定义的Realm
     * @return
     */
    @Bean
    public CustomRealm customRealm(){
        CustomRealm customRealm = new CustomRealm();
        customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return customRealm;
    }
    /**
     * 注入自定义的SessionManager
     * @return
     */
    @Bean
    public CustomSessionManager customSessionManager(){
        CustomSessionManager customSessionManager = new CustomSessionManager();
        //超时时间,默认30分钟不操作就会过期,单位豪秒
        customSessionManager.setGlobalSessionTimeout(20000);
        return customSessionManager;
    }
}

7.6.自定义SessionManager验证

public class CustomSessionManager extends DefaultWebSessionManager {
    private static final String TOKEN="token";
    //调用父类构造方法,以防后续有人修改构造,空构造覆盖,会出问题
    public CustomSessionManager() {
        super();
    }
    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        String sessionId = WebUtils.toHttp(request).getHeader(TOKEN);
        //如果sessionId不为空,就调用自定义的逻辑,如果为空就调用父类的方法
        if(sessionId!=null){
            //调用shiro内部的校验,检测sessionId是否存在,是否过期
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
                    ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return sessionId;
        }else{
            return super.getSessionId(request,response);
        }
    }
}

6a2bdd211eba4af387ebe25f15c699ff.jpg

7.7.API拦截验证案例

(1)AdminController

@RestController
@RequestMapping("/admin")
public class AdminController {
    @RequestMapping("/order")
    public JsonData findOrder(){
        Map<String,String> recordMap = new HashMap<>();
        recordMap.put("SpringBoot入门到高级实战","300元");
        recordMap.put("Cloud微服务入门到高级实战","877元");
        recordMap.put("分布式缓存Redis","990元");
        return JsonData.buildSuccess(recordMap);
    }
}

(2)LogoutController

@RestController
public class LogoutController {
    @RequestMapping("/logout")
    public JsonData logout(){
        String username = (String)SecurityUtils.getSubject().getPrincipal();
        if(username!=null){
            SecurityUtils.getSubject().logout();
            return JsonData.buildSuccess("logout成功");
        }
        return JsonData.buildError("logout失败");
    }
}

(3)OrderController

@RestController
@RequestMapping("/authc")
public class OrderController {
    @RequestMapping("/save")
    public JsonData findMyPlayRecord(){
        Map<String ,String> recordMap = new HashMap<>();
        recordMap.put("SpringBoot入门到高级实战","第8章第1集");
        recordMap.put("Cloud微服务入门到高级实战","第4章第10集");
        recordMap.put("分布式缓存Redis","第10章第3集");
        return JsonData.buildSuccess(recordMap);
    }
}

(4)pubController

@RestController
@RequestMapping("/pub")
public class PubController {
    @RequestMapping("/need_login")
    public JsonData needLogin(){
        return JsonData.buildSuccess("温馨提示:请使用对应的账号登录",-2);
    }
    @RequestMapping("not_permit")
    public JsonData notPermit(){
        return JsonData.buildSuccess("温馨提示:拒绝访问,没权限",-3);
    }
    @RequestMapping("/index")
    public JsonData index(){
        List<String> videoList = new ArrayList<>();
        videoList.add("Mysql零基础入门到实战 数据库教程");
        videoList.add("Redis高并发高可用集群百万级秒杀实战");
        videoList.add("Zookeeper+Dubbo视频教程 微服务教程分布式教程");
        videoList.add("2019年新版本RocketMQ4.X教程消息队列教程");
        videoList.add("微服务SpringCloud+Docker入门到高级实战");
        return JsonData.buildSuccess(videoList);
    }
    @PostMapping("/login")
    public JsonData login(@RequestBody UserQuery userQuery, HttpServletRequest request, HttpServletResponse response){
        Subject subject = SecurityUtils.getSubject();
        System.out.println("userQuery:"+userQuery);
        Map<String,Object> info = new HashMap<>();
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(userQuery.getUsername(),userQuery.getPwd());
            subject.login(token);
            info.put("session_id",subject.getSession().getId());
            return JsonData.buildSuccess(info,"登录成功");
        }catch (Exception e){
            info.put("session_id",subject.getSession().getId());
            return JsonData.buildError("账号或密码错误");
        }
    }
}

(5)VideoController

@RestController
@RequestMapping("/video")
public class VideoController {
    @RequestMapping("/update")
    public JsonData updateVideo(){
        return JsonData.buildSuccess("video 更新成功");
    }
}

(6)用户角色权限分配图


cc81ba30722448459674c12bb2aab38e.jpg

(7)测试


44a8c75948154838a46317be982787e9.jpgb8cad8c3a0ca446b9496508d944c9bcc.jpg

7.8.Shiro密码加密处理

@SpringBootTest
class RbacShiroApplicationTests {
    @Test
    void contextLoads() {
        //加密算法
        String hashName = "md5";
        //密码明文
        String pwd = "123456";
        //加密函数,使用shiro自带的
        SimpleHash hash = new SimpleHash(hashName, pwd, null, 2);
        System.out.println(hash);
    }
}


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9月前
|
前端开发 数据安全/隐私保护
若依框架---权限控制角色设计
若依框架---权限控制角色设计
1401 0
|
8月前
|
存储 安全 数据库
管理端开发如何快速理解并实现权限控制总结
管理端开发如何快速理解并实现权限控制总结
|
存储 前端开发 安全
权限管理与Shiro入门-1
权限管理与Shiro入门-1
200 1
|
存储 缓存 安全
权限管理与Shiro入门-2
权限管理与Shiro入门-2
85 2
|
缓存 安全 Java
【权限管理框架】一文看懂Shiro权限管理框架!1
【权限管理框架】一文看懂Shiro权限管理框架!
|
NoSQL Java Redis
【权限管理框架】一文看懂Shiro权限管理框架!3
【权限管理框架】一文看懂Shiro权限管理框架!
|
存储 数据库 数据安全/隐私保护
Shiro角色和权限管理
Shiro角色和权限管理
|
存储 缓存 前端开发
2021年你还不会Shiro?----8.使用Shiro实现权限管理(前后端)
这是一个系列的文章,这是第八篇,如果只是看了这一篇或者对于Shiro没有基础的人,看到这一篇可能并不会有多大收益。前面几篇文章已经介绍了Shiro+JSP+SpringBoot+Mybatis+mysql的整合,并实现了使用MD5+盐+hash散列的方式对密码进行加密的注册登录功能。这篇是基于之前的文章进行写作的,下面就要说下登录完成后怎么实现授权操作。也就是怎么使用Shiro实现权限管理,前后端的授权是分开的,准确的说是没有关系的,所以这里也是对前后端的授权操作分开讲解。
398 0
2021年你还不会Shiro?----8.使用Shiro实现权限管理(前后端)
|
缓存 安全 Java
springboot简单集成shiro权限管理
springboot简单集成shiro权限管理
176 0
springboot简单集成shiro权限管理
|
开发框架 前端开发 安全
基于MVC框架实现权限控制简介
基于MVC框架实现权限控制简介
221 0
基于MVC框架实现权限控制简介