1. 程式人生 > >SpringBoot整合Shiro許可權管理框架

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