1. 程式人生 > 實用技巧 >Springboot:springboot整合Shiro(JdbcRealm 方式)

Springboot:springboot整合Shiro(JdbcRealm 方式)

1、匯入依賴

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true
</optional> </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> <!-- MyBatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1
.0</version> </dependency> <!-- mysql驅動 依賴 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> <scope>runtime</scope> </dependency> <!--Druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1
.10</version> </dependency> <!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> </dependencies>

2、書寫配置檔案

spring:
  datasource:
    druid:
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/shiro?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
      initialSize: 5
      minIdle: 5
      maxActive: 20
      maxWait: 60000
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 300000
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true

3、配置過濾器

@Configuration
public class ShiroConfig {
    @Bean
    public JdbcRealm getJdbcRealm(DataSource dataSource){
        //JdbcRealm會自行從資料庫查詢使用者以及許可權資料(資料庫的表結構要符合JdbcRealm的規範)
        JdbcRealm jdbcRealm=new JdbcRealm();
        jdbcRealm.setDataSource(dataSource);
        //JdbcRealm預設開啟認證功能,需要手動開啟授權功能
        jdbcRealm.setPermissionsLookupEnabled(true);
        return jdbcRealm;
    }

    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(JdbcRealm jdbcRealm){
        DefaultWebSecurityManager defaultSecurityManager=new DefaultWebSecurityManager();
        defaultSecurityManager.setRealm(jdbcRealm);//SecurityManager完成校驗需要realm
        return defaultSecurityManager;
    }

    @Bean
    public ShiroFilterFactoryBean  shiroFilterFactoryBean(DefaultSecurityManager securityManager){
        ShiroFilterFactoryBean filter=new ShiroFilterFactoryBean();
        //過濾器是shiro執行許可權的核心,進行認證和授權是需要SecurityManager的
        filter.setSecurityManager(securityManager);
        //設定shiro的攔截規則
        Map<String,String> filterMap=new HashMap<>();
        //user:使用remberme的使用者可訪問
        //perms:對應許可權可訪問
        //role:對應的角色才能訪問
        filterMap.put("/","anon");//anon表示不攔截(匿名使用者可訪問)
        filterMap.put("/login.html","anon");
        filterMap.put("/regist.html","anon");
        filterMap.put("/user/login","anon");
        filterMap.put("/user/regist","anon");
        filterMap.put("/static/**","anon");
        filterMap.put("/**","authc");//authc表示認證使用者可訪問
        filter.setFilterChainDefinitionMap(filterMap);
        filter.setLoginUrl("/login.html");
        //設定未授權訪問的頁面
        filter.setUnauthorizedUrl("/login.html");
        return filter;
    }
}

使用資料庫中的使用者資料的時候,這裡的realm是不同的,下面的安全管理器和過濾器是一樣的

4、頁面跳轉的controller

@Controller
public class PageController {
    @RequestMapping("/login.html")
    public String login(){
        return "login";
    }

    @RequestMapping("/")
    public String login1(){
        return "login";
    }

    @RequestMapping("/index.html")
    public String index(){
        return "index";
    }
}

5、認證

在service層書寫方法,根據使用者輸入的使用者名稱和密碼完成使用者身份的校驗:

@Service
public class UserService {
    public void checkLogin(String username,String password) throws Exception{
        Subject subject= SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(username,password);
        subject.login(token);
    }
}

書寫controller呼叫service層的校驗方法,根據校驗的結果跳轉到不同的頁面並給出相應的提示資訊:

@Controller
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("login")
    public String login(String username,String password){
        try{
            userService.checkLogin(username,password);
            System.out.println("成功");
            System.out.println(username+password);
            return "index";
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("失敗");
            System.out.println(username+password);
            return "login";
        }
    }
}

登入頁面:

<body>
    <form action="/user/login">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" value="提交">
    </form>
</body>

index頁面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
   <h3>index</h3>
</body>
</html>

6、資料庫

建立一個名稱為users的表,裡面有username和password欄位:

這裡要注意表的名稱,必須為users,否則會給出出錯資訊:

必須為users的原因是我們並沒有書寫操作資料庫的程式碼,預設找的是users表中的資料,因此,名稱數固定的

7、 測試

(1)輸入資料庫中存在的使用者資訊

(2)輸入資料庫中不存在的使用者資訊

跳轉到的是登入頁面,未能跳轉index頁面,登入失敗