SpringBoot整合Shiro权限管理框架

项目目录结构

项目目录结构

1.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wpf</groupId>
    <artifactId>shiro-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
    </dependencies>

</project>

2.application.yml

server:
  port: 8080
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/spring_shiro?useUnicode=true&amp;characterEncoding=UTF-8
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
  freemarker:
    suffix: .html
    cache: false
    template-loader-path: classpath:/templates
mybatis:
  #mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.wpf.pojo
  configuration:
    map-underscore-to-camel-case: true

3.3个实体类   用户,角色,权限

package com.wpf.pojo;


/**
 * 用户
 */
public class User {


    private Long id;

    private String name;
    private Integer password;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPassword() {
        return password;
    }

    public void setPassword(Integer password) {
        this.password = password;
    }
}
package com.wpf.pojo;

/**
 * 角色
 */
public class Role {


    private Long id;
    private String roleName;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}
package com.wpf.pojo;

/**
 * 权限
 */
public class Permission {


    private Long id;
    private String permission;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

}

4.dao层 3个对应实体类 用来查询用户,角色,和权限

@Repository
public interface UserDao {

    @Select("select * from user where name = #{name}")
    User findByName(String name);
}
@Repository
public interface RoleDao {

    @Select("select * from role where user_id = #{id}")
    List<Role> findByUserId(Long id);
}
@Repository
public interface PermissionDao {

    @Select("select * from permission where role_id = #{id}")
    List<Permission> findByRoleId(Long id);
}

5.自定义 Realm  用于测试直接调用了Dao层,跳过了service层,LoginService可替换为UserDao

//实现AuthorizingRealm接口用户用户认证
public class MyShiroRealm extends AuthorizingRealm {

    //用于用户查询
    @Autowired
    private LoginServiceImpl loginService;
    //用户角色查询
    @Autowired
    private RoleDao roleDao;
    //用于权限查询
    @Autowired
    private PermissionDao permissionDao;

    //角色权限和对应权限添加
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取登录用户名
        String name= (String) principalCollection.getPrimaryPrincipal();
        //查询用户名称
        User user = loginService.findByName(name);
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //通过用户查寻角色
        List<Role> roles = roleDao.findByUserId(user.getId());
        for (Role role:roles) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());
            //通过角色查询权限
            List<Permission> permissions = permissionDao.findByRoleId(role.getId());
            for (Permission permission:permissions){
                //添加角色权限
                simpleAuthorizationInfo.addStringPermission(permission.getPermission());
            }
        }


        return simpleAuthorizationInfo;
    }

    //用户认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        //获取用户信息
        String name = authenticationToken.getPrincipal().toString();
        User user = loginService.findByName(name);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
            return simpleAuthenticationInfo;
        }
    }
}

6.将自定义Realm配置进Shiro,配置过滤条件

@Configuration
public class ShiroConfiguration {

    //将自己的验证方式加入容器
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<String, String>();
        //登出
        map.put("/logout","logout");
        //对所有用户认证
        map.put("/**","authc");
        //管理员,需要角色权限 “admin” 访问admin下面的路径需要admin角色
        map.put("/admin/**", "roles[admin]");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/login");
        //首页
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //加入注解的使用,不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

7.controller层 测试登录,退出,和权限

@Controller
public class LoginResource {

    //进入登录页面
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(){
        return "/logins";
    }

    //post登录
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    @ResponseBody
    public String login(String username,String password){
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                username,
                password);
        //进行验证,这里可以捕获异常,然后返回对应信息
        subject.login(usernamePasswordToken);

        if(subject.hasRole("admin")){
            System.out.println("admin角色");
        }
        if(subject.isPermitted("create")){
            System.out.println("有create权限");
        }
        return "登录成功";
    }

    //跳转到主页
    @RequestMapping(value = "/index")
    public String index(){
        return "indexx";
    }

    //退出登录
    @RequestMapping(value = "/logout")
    public String logout(){
        return "logout";
    }

    //错误页面展示
    @RequestMapping(value = "/error",method = RequestMethod.POST)
    @ResponseBody
    public String error(){
        return "error ok!";
    }


    //注解的使用
    @RequiresRoles("admin")
    @RequiresPermissions("create")
    @RequestMapping(value = "/create")
    @ResponseBody
    public String create(){
        return "Create success!";
    }

}

8.基本的登录,主页 页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
    <input type="submit" value="登录">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    主页
</body>
</html>

9.数据库数据

用户表

用户

角色表

角色

权限表

权限表

项目源码:https://download.csdn.net/download/weixin_42460179/10728459

猜你喜欢

转载自blog.csdn.net/weixin_42460179/article/details/83114008