SpringBoot整合Shiro实现权限控制

SpringBoot整合Shiro实现权限控制

引言:

      本文主要分享了SpringBoot整合Shiro实现权限控制的案例,Shiro的认证流程:包括环境的搭建、数据库的添加、实体类映射文件、使用源生Shiro、MD5加密后的密钥登录问题、基于注解的开发(均附源码);



在这里插入图片描述

1. 新建项目

1.1 选择构建项目的类型_aliyun

填入aliyun网址

2.5 项目描述

在这里插入图片描述

2.6 指定SpringBoot版本和需要的依赖

本项目选择2.1.14版本,加入了Lombok、Spring Web、Thymeleaf、JDBC API、MyBatis Framework、MySQL Driver依赖

在这里插入图片描述

2. 创建数据库

2.1 创建tb_sys_user表

CREATE TABLE `tb_sys_user` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `loginName` varchar(20) NOT NULL,
  `password` varchar(255) NOT NULL,
  `state` tinyint(255) DEFAULT NULL,
  `createTime` datetime DEFAULT NULL,
  `realname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

2.2 创建tb_user_role表

CREATE TABLE `tb_user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.3 创建tb_sys_role表

CREATE TABLE `tb_sys_role` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) NOT NULL,
  `role_desc` varchar(255) DEFAULT NULL,
  `if_vilid` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

2.4 创建tb_sys_permission表

CREATE TABLE `tb_sys_permission` (
  `permission_id` int(11) NOT NULL AUTO_INCREMENT,
  `per_name` varchar(255) DEFAULT NULL,
  `menu_name` varchar(255) DEFAULT NULL,
  `menu_type` varchar(255) DEFAULT NULL,
  `menu_url` varchar(255) DEFAULT NULL,
  `menu_code` varchar(255) DEFAULT NULL,
  `parent_code` varchar(255) DEFAULT NULL,
  `per_desc` varchar(255) DEFAULT NULL,
  `if_vilid` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`permission_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

2.5 创建tb_role_permission表

CREATE TABLE `tb_role_permission` (
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3. 配置文件

3.1 配置初始化文件application.properties


# 应用服务 WEB 访问端口
server.port=8080
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/dbtemp?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

mybatis.mapper-locations=classpath:mapping/*Mapper.xml
mybatis.type-aliases-package=com.sx.kak.po

3.2 pom文件

 <!--添加shiro依赖-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>

<!--添加连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.26</version>
</dependency>

4. 实体类编写

4.1 SysUser.java

package com.sx.kak.po;

import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * Created by Kak on 2020/9/3.
 */
@Data
public class SysUser implements Serializable{

    private Integer  userid;
    private String loginName;
    private String password;
    private Integer state;
    private Date createTime;
    private String realname;
}

4.2 SysPerm.java

package com.sx.kak.po;

import lombok.Data;

import java.io.Serializable;

/**
 * Created by Kak on 2020/9/3.
 */
@Data
public class SysPerm implements Serializable{
    private Integer permId;
    private String permName;
    private String menuName;
    private String menuType;
    private String menuUrl;
    private String parentCode;
    private String permDesc;
    private Integer ifValid;
}

5. 数据访问层接口编写

5.1 SysUserMapper.java

package com.sx.kak.mapper;

import com.sx.kak.po.SysUser;
import org.springframework.stereotype.Repository;

/**
 * Created by Kak on 2020/9/3.
 */

public interface SysUserMapper {
    //根据用户登录名查询用户对象
    public SysUser findUserByLoginName(String username);
}

5.2 SysPermMapper.java

package com.sx.kak.mapper;

import com.sx.kak.po.SysPerm;

import java.util.List;

/**
 * Created by Kak on 2020/9/3.
 */
public interface SysPermMapper {
    //根据用户名查询权限清单
    public List<SysPerm> findPermsByLoginName(String username);

}

6. Mybatis映射

在resources/mapping下创建对应的映射

6.1 SysUserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sx.kak.mapper.SysUserMapper">
    <select id="findUserByLoginName" parameterType="String" resultType="com.sx.kak.po.SysUser">
        SELECT * FROM tb_sys_user WHERE loginName =#{username}
    </select>
</mapper>

6.2 SysPerMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sx.kak.mapper.SysPermMapper">
    <sql id="permColums">
        p.permission_id permId,
        per_name permName,
        menu_name menuName,
        menu_type menuType,
        menu_url menuUrl,
        menu_code menuCode,
        parent_code parentCode,
        per_desc permDesc,
        p.if_vilid ifValid
    </sql>
    <select id="findPermsByLoginName" parameterType="String" resultType="com.sx.kak.po.SysPerm">
        select
        <include refid="permColums"/>
        from
        tb_sys_user  u ,
        tb_user_role  ur,
        tb_sys_role  r,
        tb_role_permission rp,
        tb_sys_permission p
        where
        u.userid = ur.user_id
        and ur.role_id = r.role_id
        and r.role_id = rp.role_id
        and rp.permission_id = p.permission_id
        and loginName=#{username}
    </select>
</mapper>

7. 业务层开发

在service包下创建

7.1 SysPermService

package com.sx.kak.servier;

import com.sx.kak.po.SysPerm;
import com.sx.kak.po.SysUser;

import java.util.List;

/**
 * Created by Kak on 2020/9/3.
 */
public interface SysPermService {
    //根据用户名查询用户信息
    public SysUser findUserByNameService(String username);
    //根据用户名查询权限信息
    public List<SysPerm> findPermsByNameService(String username);
}

7.2 SysPermServiceImpl

package com.sx.kak.servier.impl;

import com.sx.kak.mapper.SysPermMapper;
import com.sx.kak.mapper.SysUserMapper;
import com.sx.kak.po.SysPerm;
import com.sx.kak.po.SysUser;
import com.sx.kak.servier.SysPermService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created by Kak on 2020/9/3.
 */
@Service
public class SysPermServiceImpl implements SysPermService{
    @Autowired(required = false)
    private SysUserMapper userMapper;
    @Autowired(required = false)
    private SysPermMapper permMapper;
    @Override
    public SysUser findUserByNameService(String username) {
        SysUser userByLoginName = userMapper.findUserByLoginName(username);
        return userByLoginName;
    }

    @Override
    public List<SysPerm> findPermsByNameService(String username) {
        List<SysPerm> permsByLoginName = permMapper.findPermsByLoginName(username);
        return permsByLoginName;
    }
}

8. 前端页面

前端只是简单的提示信息,不是重点;

在这里插入图片描述

在这里插入图片描述

9. 核心板块编写_初级版本

9.1 控制层接口开发_ShiroController

完成界面的跳转,登录处理、登出处理

package com.sx.kak.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Created by Kak on 2020/9/3.
 */
@Controller
public class ShiroController {
    @RequestMapping("/login")
    public String showLogin(){
        return "login";
    }
    @RequestMapping("/one")
    public String showOne(){
        return "one";
    }
    @RequestMapping("/two")
    public String showTwo(){
        return "two";
    }
    @RequestMapping("/unauth")
    public String showUnauth(){
        return "unauth";
    }
    @RequestMapping("/main")
    public String showMain(){
        return "main";
    }

    //登录处理
    @RequestMapping(value = "/dealLogin",method = RequestMethod.POST)
    public String dealLogin(@RequestParam("username") String username,@RequestParam("password") String password){
        //从安全管理器中获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //构建令牌对象
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try{
            //使用主体的login方法判定用户的权限
                subject.login(token);
                if(subject.isAuthenticated()){
                    return "main";
                }
        }catch (AuthenticationException ae){
            System.out.println(ae.getMessage());
        }
        return "login";
    }

    //登出处理
    @RequestMapping(value = "logout",method = RequestMethod.GET)
    public String logOut(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }
}

9.2 关于shiro的开发

9.2.1 自定义安全策略

package com.sx.kak.shiro;

import com.sx.kak.po.SysPerm;
import com.sx.kak.po.SysUser;
import com.sx.kak.servier.SysPermService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 自定义安全策略
 * Created by Kak on 2020/9/3.
 */
public class MyShiroRealm extends AuthorizingRealm{
    @Autowired
    private SysPermService permService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Object primaryPrincipal = principalCollection.getPrimaryPrincipal();
        //根据用户名查询用户权限
        List<SysPerm> permsByNameService = permService.findPermsByNameService((String) primaryPrincipal);
        if(permsByNameService!=null){
            SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
            //权限去重
            Set<String> perms = new HashSet<String>();
            for (SysPerm perm:permsByNameService){
                perms.add(perm.getPermName());
            }
            //给shiro的安全管理器授权
            simpleAuthenticationInfo.setStringPermissions(perms);
            return simpleAuthenticationInfo;
        }
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        Object principal = authenticationToken.getPrincipal();
        //根据用户名查询用户信息
        SysUser userByNameService = permService.findUserByNameService((String) principal);
        if(userByNameService!=null){
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, userByNameService.getPassword(), getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

9.2.2 自定义Shiro配置管理

package com.sx.kak.config;

import com.sx.kak.shiro.MyShiroRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义shiro配置管理
 * 程序加载时,已经初始化
 * Created by Kak on 2020/9/3.
 */
@Configuration  //标注此类为一个配置管理类,自动备spring管理
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
        //创建一个Shiro的拦截过滤器对象
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //给过滤器设定安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<>();
        //对/main的请求需要认证后才可访问
        map.put("/main","authc");
        //用户必须登录后且拥有user_edit权限才可访问/one
        map.put("/one","perms[user_edit]");
        //用户必须登录后且拥有user_forbidden权限才可访问/two
        map.put("/two","perms[user_forbidden ]");
        //配置shiro过滤器拦截策略
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        //用户无权访问时,导航的地址
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
        //其他需要用户访问的登录导航
        shiroFilterFactoryBean.setLoginUrl("/login");
        return shiroFilterFactoryBean;
    }
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager  securityManager(@Qualifier("myRealm") AuthorizingRealm authorizingRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        给安全管理器配置安全策略
        securityManager.setRealm(authorizingRealm);
        return securityManager;
    }
    @Bean(name = "myRealm")
    public MyShiroRealm myShiroRealm(){
        //创建自定义的安全策略
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }
}

9.3 初级整合功能测试

在这里插入图片描述

在这里插入图片描述

9.4 流程思路

在login页面admin登录,跳转到index界面,对one页面有权限,跳转one页面,对two页面无权限跳转到unauth页面,登出返回到登录页面;

10. 核心板块编写_使用Shiro的注解

在开发中使用手工注入,会增大开发的工作量,因此使用注解,在需要设置权限的地方加上注解,可以缓解该情况;

10.1 修改ShiroConfig

在ShiroConfig.java中注释掉原先使用路径过滤的权限拦截语句

在这里插入图片描述

10.2 开启Shiro注解

在ShiroConfig.java类中添加开启Shiro的注解

  • 开启Shiro注解(@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,配置两个bean:DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor;
//开启Shiro注解(如@RequiresRoles,@RequiresPermissions),
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
    DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    advisorAutoProxyCreator.setProxyTargetClass(true);
    return advisorAutoProxyCreator;
}

//开启aop注解支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
    return authorizationAttributeSourceAdvisor;
}

10.3 修改UserController.java

在UserController.java中需要添加权限的URL的位置添加注解

在这里插入图片描述

10.4 测试

当登录成功后,访问有权限的正常访问;没有权限的会出现以下界面;回台会抛出UnauthorizedException异常;

在这里插入图片描述

10.5 aop拦截抛出的异常

在执行过程中,如果没有error界面,或者其他情况没有走到Shiro的异常处理时,为了保证代码的合理性加入AOP拦截;抛出相应的异常后跳转到指定页面;

package com.sx.kak.exception;

import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * Created by Kak on 2020/9/3.
 */
@ControllerAdvice   //标识此类为一个捕获controller的通知(aop)
public class GlobalExceptionController {
    @ExceptionHandler(value={UnauthorizedException.class})
    public String handlerException(){
        return "/unauth";
    }
}

加入AOP拦截,成功拦截该异常;

在这里插入图片描述

11. 核心板块编写_ShiroMD5加密

在数据库表中存的密码应该是加密后的密文不应该是明文,使用MD5加密算法;

11.1 生成MD5密钥的两种方法

@Test
public void testMd51(){
    String pwd ="1234";
    String salt ="admin2";
    Md5Hash md5Hash = new Md5Hash(pwd,salt,2);
    String string1 = md5Hash.toString();
    System.out.println(string1);
    SimpleHash md5 = new SimpleHash("MD5", pwd, salt, 2);
    System.out.println(md5.toString());
}
3511f3360d453c63dd74c95303dcca51

11.2 修改ShiroConfig.java

在ShiroConfig.java中加入HashedCredentialsMatcher,设定匹配算法的名称、hash的次数并在自定义的策略里面添加凭证匹配对象;

在这里插入图片描述

11.3 修改MyShiroRealm.java

修改MyShiroRealm中的认证,加入加盐操作;

在这里插入图片描述

12. 加入注解和加密操作代码

改动较大的代码

12.1 ShiroConfig.java

package com.sx.kak.config;

import com.sx.kak.shiro.MyShiroRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义shiro配置管理
 * 程序加载时,已经初始化
 * Created by Kak on 2020/9/3.
 */
@Configuration  //标注此类为一个配置管理类,自动备spring管理
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
        //创建一个Shiro的拦截过滤器对象
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //给过滤器设定安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<>();
        //匿名可访问
        map.put("/before/*","anon");
        //对/main的请求需要认证后才可访问
        map.put("/main","authc");
        //不进行手工配置过滤器访问策略,采用注解模式,将访问策略迁移至controller层
        /*//用户必须登录后且拥有user_edit权限才可访问/one
        map.put("/one","perms[user_edit]");
        //用户必须登录后且拥有user_forbidden权限才可访问/two
        map.put("/two","perms[user_forbidden ]");*/
        //配置shiro过滤器拦截策略
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        //用户无权访问时,导航的地址
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
        //其他需要用户访问的登录导航
        shiroFilterFactoryBean.setLoginUrl("/login");
        return shiroFilterFactoryBean;
    }
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager  securityManager(@Qualifier("myRealm") AuthorizingRealm authorizingRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        给安全管理器配置安全策略
        securityManager.setRealm(authorizingRealm);
        return securityManager;
    }
    @Bean(name = "myRealm")
    public MyShiroRealm myShiroRealm(@Qualifier("credentialsMatcher") CredentialsMatcher credentialsMatcher){
        //创建自定义的安全策略
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        //给自定义的realm添加凭证匹配器对象
        myShiroRealm.setCredentialsMatcher(credentialsMatcher);
        return myShiroRealm;
    }

    @Bean(name = "credentialsMatcher")
    public CredentialsMatcher credentialsMatcher(){
        //创建一个凭证匹配器对象
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //设值匹配器算法名称
        credentialsMatcher.setHashAlgorithmName("MD5");
        //设值hash次数
        credentialsMatcher.setHashIterations(2);
        return credentialsMatcher;
    }

	//开启Shiro注解(如@RequiresRoles,@RequiresPermissions),
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

     //开启aop注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

12.2 MyShiroRealm.java

package com.sx.kak.shiro;

import com.sx.kak.po.SysPerm;
import com.sx.kak.po.SysUser;
import com.sx.kak.servier.SysPermService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 自定义安全策略
 * Created by Kak on 2020/9/3.
 */
public class MyShiroRealm extends AuthorizingRealm{
    @Autowired
    private SysPermService permService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Object primaryPrincipal = principalCollection.getPrimaryPrincipal();
        //根据用户名查询用户权限
        List<SysPerm> permsByNameService = permService.findPermsByNameService((String) primaryPrincipal);
        if(permsByNameService!=null){
            SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
            //权限去重
            Set<String> perms = new HashSet<String>();
            for (SysPerm perm:permsByNameService){
                perms.add(perm.getPermName());
            }
            //给shiro的安全管理器授权
            simpleAuthenticationInfo.setStringPermissions(perms);
            return simpleAuthenticationInfo;
        }
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        Object principal = authenticationToken.getPrincipal();
        //根据用户名查询用户信息
        SysUser userByNameService = permService.findUserByNameService((String) principal);
        if(userByNameService!=null){
            //SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, userByNameService.getPassword(), getName());
            //获取名字
            String salt =userByNameService.getLoginName();
            //将名字设置为盐
            ByteSource mysalt = ByteSource.Util.bytes(salt);
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, userByNameService.getPassword(),mysalt, getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

12.3 ShiroController.java

package com.sx.kak.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Created by Kak on 2020/9/3.
 */
@Controller
public class ShiroController {
    @RequestMapping("/login")
    public String showLogin(){
        return "login";
    }
    @RequestMapping("/one")
    @RequiresPermissions(value={"user_edit"})  //此请求需要user_edit权限才可访问
    public String showOne(){
        return "one";
    }
    @RequestMapping("/two")
    @RequiresPermissions(value={"user_forbidden"})  //此请求需要user_forbidden权限才可访问
    public String showTwo(){
        return "two";
    }
    @RequestMapping("/unauth")
    public String showUnauth(){
        return "unauth";
    }
    @RequestMapping("/main")
    public String showMain(){
        return "main";
    }

    //登录处理
    @RequestMapping(value = "/dealLogin",method = RequestMethod.POST)
    public String dealLogin(@RequestParam("username") String username,@RequestParam("password") String password){
        //从安全管理器中获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //构建令牌对象
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try{
            //使用主体的login方法判定用户的权限
                subject.login(token);
                if(subject.isAuthenticated()){
                    return "main";
                }
        }catch (AuthenticationException ae){
            System.out.println(ae.getMessage());
        }
        return "login";
    }

    //登出处理
    @RequestMapping(value = "logout",method = RequestMethod.GET)
    public String logOut(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }
}

12.4 运行界面

在这里插入图片描述

在这里插入图片描述

13. 整体的执行思路

  1. 程序开始执行,SpringBoot扫描注解,加载ShiroConfig将认证信息存入CacheManager中;
  2. 进入自定义策略,进行认证与数据库进行比对,成功后存入SessionManager;
  3. 与Controller里的登录操作接受的信息进行比对;
  4. 把前端输入用户名和密码封装到UsernamePasswordToken里,再把token注入到subject.login方法里,一旦执行shiro会自动调用shiroRealm里的登录验证方法;
  5. 进行授权,有权限isAuthenticated返回true,执行下面的代码;
  6. 其他权限的控制都是如此;
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Willing卡卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值