Shiro安全框架实现授权逻辑

Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

前言:
开发工具:idea、MySQL
开发技术:MyBatis、Spring Boot、Shiro

创建数据库及测试表

-- 创建数据库
CREATE DATABASE IF NOT EXISTS shoop DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
-- 创建用户表
create table shiro_user(
  u_id int auto_increment primary key,
  password varchar(50),
  user_name VARCHAR(100)
)
insert into shiro_user(password,user_name) values('admin','[email protected]'),('123456','[email protected]')
-- 角色表
create table shiro_user_role(
  r_id int auto_increment primary key,
  role_name varchar(50),
  user_name VARCHAR(100)
)
insert into shiro_user_role(role_name,user_name) values('admin','[email protected]'),('test','[email protected]')
-- 角色权限表
create table shiro_role_permission(
  p_id int auto_increment primary key,
  role_name varchar(50),
  perm_name VARCHAR(100)
)
insert into shiro_role_permission(role_name,perm_name) values('admin','home_manage.html'),
('admin','get.html'),('admin','delete.html'),('test','add.html')

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>five</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>five</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- spring boot mybatis依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.2.0</version>
        </dependency>
        <!-- 添加thymeleaf支持:类似于jsp的视图模板 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

         <!-- Shiro依赖 -->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

#数据源
spring.datasource.url=jdbc:mysql://localhost:3306/shoop?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

实体类(entity)

//用户表
public class ShiroUser {
    private int u_id;
    private String user_name;
    private String password;
    //省略getter和setter方法    
    }
//角色表
public class Role {
    private int r_id;
    private String role_name;
    private String user_name;
    //省略getter和setter方法    
    }
//角色权限表
public class Pejuesejuese   private int p_id;
    private String role_name;
    private String perm_name;
    //省略getter和setter方法   
    } 

接口(mapper)

//查询用户
@Mapper
public interface ShiroUserMapper {
    public ShiroUser findByName(@Param(value = "user_name") String user_name);
}
//查询用户角色
@Mapper
public interface RoleMapper {
    public Role RoleName(@Param(value = "user_name") String user_name);
}
//查询角色的权限
@Mapper
public interface PermissionMapper {
    public List<Permission> PermissionPerName(@Param(value = "role_name") String role_name);
}

myBatis配置文件(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.springboot.mapper.ShiroUserMapper">
    <select id="findByName" resultType="com.springboot.entity.ShiroUser">
         select * from shiro_user where user_name=#{user_name}
    </select>
</mapper>
<!-- 查询用户角色-->
<?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.springboot.mapper.RoleMapper">
    <select id="RoleName" resultType="com.springboot.entity.Role">
         select *from shiro_user_role where user_name=#{user_name}
    </select>
</mapper>
<!-- 查询角色的权限-->
<?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.springboot.mapper.PermissionMapper">
<select id="PermissionPerName" resultType="com.springboot.entity.Permission">
        select *from shiro_role_permission where role_name=#{role_name}
    </select>
</mapper>

业务层(service)

//查询用户
public interface ShiroUserService {
    public ShiroUser findByName(@Param(value = "user_name") String user_name);
}
//查询用户角色
public interface RoleService {
    public Role RoleName(@Param(value = "user_name") String user_name);
}
//查询角色的权限
public interface PermissionService {
    public List<Permission> PermissionPerName(@Param(value = "role_name") String role_name);
}

业务实现层(service.impl)

//查询用户
@Service
public class ShiroUserServiceImp implements ShiroUserService {
    @Resource
    private ShiroUserMapper shiroUserMapper;
    @Override
    public ShiroUser findByName(String user_name) {
        //ShiroUser user = shiroUserMapper.findByName(user_name);
        return shiroUserMapper.findByName(user_name);
    }
}
//查询用户角色
@Service
public class RoleServiceImpl implements RoleService {
    @Resource
    public RoleMapper rolemapper;
    @Override
    public Role RoleName(String user_name) {
        //Role user = rolemapper.RoleName(user_name);
        return rolemapper.RoleName(user_name);
    }
}
//查询角色的权限
@Service
public class PermissionServiceImpl implements PermissionService {
    @Resource
    public PermissionMapper permissionMapper;
    @Override
    public List<Permission> PermissionPerName(String role_name) {
        //List<Permission> permission = permissionMapper.PermissionPerName(role_name);
        return permissionMapper.PermissionPerName(role_name);
    }
}

逻辑控制层(Controller)

public class UserRealm extends AuthorizingRealm {

     //认证
    @Resource
    public ShiroUserService shiroUserService;
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        ShiroUser user = shiroUserService.findByName(token.getUsername());
        //2.判断密码
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
    //授权
    @Resource
    public RoleService roleService;
    @Resource
    public PermissionService permissionService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前用户的ID
        Subject subject = SecurityUtils.getSubject();
        ShiroUser user  = (ShiroUser) subject.getPrincipal();
        //查询用户的角色(身份)
        Role role = roleService.RoleName(user.getUser_name());
        //查询用户角色权限
        List<Permission> permission = null;
        try {
            permission = permissionService.PermissionPerName(role.getRole_name());
        } catch (Exception e) {
            e.printStackTrace();
        }
        Set<String> permissions = new HashSet<String>();
        for(Permission p:permission){
            permissions.add(p.getPerm_name());
        }
        info.setStringPermissions(permissions);
        return info;
    }
}

@Configuration
public class ShiroConfig {
    //创建Realm
    @Bean(name = "userRealm")
    public UserRealm getUserRealm(){
        UserRealm userRealm = new UserRealm();
        return userRealm;
    }

    //创建DefaultWebSecurityManager(安全管理器,关联Realm)
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联Realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建ShiroFilterFactoryBean(用户主体,把操作交给SecurityManager)
    @Bean(name = "DefaultWebSecurityManager")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //添加shiro内置过滤器,可以实现相关权限拦截
        Map<String,String> filterMap = new LinkedHashMap<String, String>();
        filterMap.put("/tet/test","anon");
        filterMap.put("/tet/login","anon");
        //Tips:当授权拦截后,Shiro会自动跳转到未授权界面
        filterMap.put("/tet/add", "perms[add.html]");
        filterMap.put("/tet/update", "perms[get.html]");
        filterMap.put("/tet/delete", "perms[delete.html]");
        filterMap.put("/tet/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        shiroFilterFactoryBean.setLoginUrl("/tet/toLogin");
        shiroFilterFactoryBean.setSuccessUrl("/tet/hello");
        shiroFilterFactoryBean.setUnauthorizedUrl("/tet/noAuth");
        return shiroFilterFactoryBean;
    }

    //配置ShiroDialect,用于thymeleaf和shiro标签的配合使用
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}


@RequestMapping("/tet")
@Controller
public class testController {
    @RequestMapping("/login")
    public String login(String user_name, String password){

        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user_name,password);
        try {
            subject.login(token);
            return "test";
        } catch (AuthenticationException e) {
            return "a";
        }
    }
    @RequestMapping("/test")
    public String test(){
        return "home";
    }
    @RequestMapping("/add")
    public String add() {
        return "add";
    }
    @RequestMapping("/update")
    public String update(){
        return "update";
    }
    @RequestMapping("/delete")
    public String delete(){
        return "delete";
    }
    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }
    @RequestMapping("/hello")
    public String hello(){
        return "a";
    }
    @RequestMapping("/noAuth")
    public String noAuth(){
        return "s";
    }
}

登录HTML

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/tet/login" method="post">
    用户名:<input type="text" name="user_name"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="login">
</form>
</body>
</html>

首页HTML

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<shiro:hasPermission name="add.html">
    用户添加:<a href="add">添加用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="get.html">
    用户修改:<a href="update">修改用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="delete.html">
    用户删除:<a href="delete">删除用户</a><br>
</shiro:hasPermission>

</body>
</html>

项目源码https://pan.baidu.com/s/1Lcn_ovMz48UoKz7p_xQsHA提取码:m55s

发布了22 篇原创文章 · 获赞 2 · 访问量 1136

猜你喜欢

转载自blog.csdn.net/javaasd/article/details/105148008