Spring Boot 與Shrio整合

分析Shrio的核心API

Subject:用戶主體(把操作交給SecurityManager)
SecurityManager:安全管理器(關(guān)聯(lián)Realm)
Realm:Shiro連接數(shù)據(jù)的橋梁

Spring Boot整合Shiro

(1) 導(dǎo)入依賴

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0></version>
<dependency/>

(2)自定義Realm類

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * 自定義Realm
 */
public class UserRealm extends AuthorizingRealm {
    /**
     * 執(zhí)行授權(quán)邏輯
     * @param principalCollection
     * @return
     */
        //@Qualifier("userRealm")將userRealm注入當(dāng)前類
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("執(zhí)行授權(quán)邏輯");
        return null;
    }

    /**
     * 執(zhí)行認(rèn)證邏輯
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("執(zhí)行認(rèn)證邏輯");
        return null;
    }
}

(3)編寫Shiro配置類(*)
建立shiro的配置類

/**
 * shiro配置類
 */
@Configuration
public class ShiroConfig {
    /**
     * 創(chuàng)建ShiroFilterFactoryBean
     */
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //設(shè)置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        return shiroFilterFactoryBean;

    }


    /**
     * 創(chuàng)建DefaultWebSecurityManager
     */
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        //@Qualifier("userRealm")將userRealm注入當(dāng)前類
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //關(guān)聯(lián)realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    /**
     * 創(chuàng)建Realm
     */
    @Bean
    public UserRealm getRealm(){
        return new UserRealm();
    }

(4) 使用Shiro內(nèi)置過濾器實(shí)現(xiàn)頁面攔截,在ShiroConfig中配置

           @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //設(shè)置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //添加Shrio內(nèi)置過濾器
            /**
             * Shiro內(nèi)置過濾器,可以實(shí)現(xiàn)權(quán)限相關(guān)的攔截器
             *     常用的過濾器:
             *        anon:無需認(rèn)證(登錄)可以訪問
             *        authc:必須認(rèn)證才可以訪問
             *        user:如果使用rememberMe的功能可以直接訪問
             *        perms:該資源必須得到資源權(quán)限才可以訪問
             *        role:該資源必須得到角色權(quán)限才可以訪問
             */
            Map<String ,String> filterMap = new LinkedHashMap<>();
//        filterMap.put("/add","authc");
//        filterMap.put("/update","authc");
            filterMap.put("/login","anon");
            filterMap.put("/tologin","anon");
            filterMap.put("/getinfo","anon");
            filterMap.put("/*","authc");
        shiroFilterFactoryBean.setLoginUrl("/tologin");   //自定義設(shè)置攔截跳轉(zhuǎn)登錄頁面,默認(rèn)是login.jsp
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;

    }

UserController中設(shè)置登錄

    @PostMapping (value = "/login")
    public String login(String name,String password,Model model){
        /**
         * 使用Shiro編寫認(rèn)證操作
         */
        //1.獲取SUbject
        Subject subject = SecurityUtils.getSubject();
        //2分裝用戶數(shù)據(jù)
        UsernamePasswordToken token = new UsernamePasswordToken(name,password);
        //3.執(zhí)行登錄方法
        try {
            subject.login(token);
            //登錄成功
            return "redirect:getinfo";
        } catch (UnknownAccountException e) {   //UnknownAccountException shiro用戶名不存在拋異常
           // e.printStackTrace();
            //登錄失敗
            model.addAttribute("msg","用戶名不存在");
            return "login";
        }catch (IncorrectCredentialsException e) {
            //e.printStackTrace();
            //登錄失敗
            model.addAttribute("msg","密碼錯(cuò)誤");
            return "login";
        }

在UserRealm中,執(zhí)行認(rèn)證邏輯中,編寫登錄邏輯

    /**
     * 執(zhí)行認(rèn)證邏輯
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("執(zhí)行認(rèn)證邏輯");
        //假設(shè)數(shù)據(jù)庫的用戶名和密碼  模擬數(shù)據(jù)庫
        String name = "liwei";
        String password = "123456";
        //編寫shiro判斷邏輯,判斷用戶名和密碼
        //1.判斷用戶名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        if(!token.getUsername().equals(name)){
            //用戶名不存在
            return null;  //shiro底層會(huì)拋出UnKnowAccountExceeption
        }
          //2 判斷密碼
        return new SimpleAuthenticationInfo("",password,"");
    }

整合mybatis

添加依賴

   <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

編寫application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.108.128:3306/tensquare_user
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource    #druid數(shù)據(jù)源


mybatis:
  type-aliases-package: com.liwei.domain  #配置實(shí)體路徑在mapper.xml中,返回實(shí)體可以不用寫前置路徑
  mapper-locations: mapperXml/*.xml

在啟動(dòng)類上加掃mapper(dao)注解

@SpringBootApplication
@MapperScan("com.liwei.shiro.mapper")
public class ShiroApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class);
    }
}

mapper

public interface UserMapper {

    User findByMobil(String mobile);
}

service

public interface UserService {
    User findByMobil(String mobile);
}

serviceimpl

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User findByMobil(String mobile) {
        return userMapper.findByMobil(mobile);
    }
}

controller

    @PostMapping (value = "/login")
    public String login(String mobile,String password,Model model){
        /**
         * 使用Shiro編寫認(rèn)證操作
         */
        //1.獲取SUbject
        Subject subject = SecurityUtils.getSubject();
        //2分裝用戶數(shù)據(jù)
        UsernamePasswordToken token = new UsernamePasswordToken(mobile,password);
        //3.執(zhí)行登錄方法
        try {
            subject.login(token);
            //登錄成功
            return "redirect:getinfo";
        } catch (UnknownAccountException e) {
           // e.printStackTrace();
            //登錄失敗
            model.addAttribute("msg","用戶名不存在");
            return "login";
        }catch (IncorrectCredentialsException e) {
            //e.printStackTrace();
            //登錄失敗
            model.addAttribute("msg","密碼錯(cuò)誤");
            return "login";
        }
    }
}

在自定義Realm中編寫登錄驗(yàn)證

/**
 * 自定義Realm
 */
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    /**
     * 執(zhí)行授權(quán)邏輯
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("執(zhí)行授權(quán)邏輯");
        return null;
    }
    /**
     * 執(zhí)行認(rèn)證邏輯
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("執(zhí)行認(rèn)證邏輯");
        //假設(shè)數(shù)據(jù)庫的用戶名和密碼  模擬數(shù)據(jù)庫
        //編寫shiro判斷邏輯,判斷用戶名和密碼
        //1.判斷用戶名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        User user = userService.findByMobil(token.getUsername());

        if(user==null){
            //用戶名不存在
            return null;  //shiro底層會(huì)拋出UnKnowAccountExceeption
        }
          //2 判斷密碼
        return new SimpleAuthenticationInfo("",user.getPassword(),"");
    }
}

使用shiro內(nèi)置過濾器攔截資源

/**
 * shiro配置類
 */
@Configuration
public class ShiroConfig {
    /**
     * 創(chuàng)建ShiroFilterFactoryBean
     */
           @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //設(shè)置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //添加Shrio內(nèi)置過濾器
            /**
             * Shiro內(nèi)置過濾器,可以實(shí)現(xiàn)權(quán)限相關(guān)的攔截器
             *     常用的過濾器:
             *        anon:無需認(rèn)證(登錄)可以訪問
             *        authc:必須認(rèn)證才可以訪問
             *        user:如果使用rememberMe的功能可以直接訪問
             *        perms:該資源必須得到資源權(quán)限才可以訪問
             *        role:該資源必須得到角色權(quán)限才可以訪問
             */
            Map<String ,String> filterMap = new LinkedHashMap<>();
//        filterMap.put("/add","authc");
//        filterMap.put("/update","authc");
            filterMap.put("/login","anon");
            filterMap.put("/tologin","anon");
            filterMap.put("/getinfo","anon");
            filterMap.put("/*","authc");
            

          TODO授權(quán)過濾器
               // 注意:當(dāng)前授權(quán)攔截后,shiro會(huì)自動(dòng)跳轉(zhuǎn)到未授權(quán)頁面
            filterMap.put("/user/add","perms[user:add]");  // user/add 攔截的路徑名
            //設(shè)置未授權(quán)提示頁面
               shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");  //自定義的提示頁面路徑  /noauth 路徑請(qǐng)求地址
        shiroFilterFactoryBean.setLoginUrl("/tologin");   //自定義設(shè)置攔截跳轉(zhuǎn)登錄頁面,默認(rèn)是login.jsp
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;

    }

    /**
     * 創(chuàng)建DefaultWebSecurityManager
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        //@Qualifier("userRealm")將userRealm注入當(dāng)前類
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //關(guān)聯(lián)realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }
    /**
     * 創(chuàng)建Realm
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
}

實(shí)現(xiàn)數(shù)據(jù)庫動(dòng)態(tài)綁定

在數(shù)據(jù)庫中添加一個(gè)權(quán)限字段
perms 數(shù)值設(shè)置為:user:add user:update user:delete

#### 增加依賴  實(shí)現(xiàn)thymeleaf動(dòng)態(tài)標(biāo)簽

<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>

**
 * 自定義Realm
 */
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    /**
     * 執(zhí)行授權(quán)邏輯
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("執(zhí)行授權(quán)邏輯");
        //給資源進(jìn)行授權(quán)
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //添加資源的授權(quán)字符串
            //info.addStringPermission("user:add");
        //到數(shù)據(jù)庫查詢當(dāng)前登錄用戶的授權(quán)字符串
        //獲取當(dāng)前登錄用戶
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        User dbUser = userService.findById(user.getId());
        info.addStringPermission(dbUser.getPerms());     //設(shè)置授權(quán)字段號(hào)
        return info;
    }
    /**
     * 執(zhí)行認(rèn)證邏輯
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("執(zhí)行認(rèn)證邏輯");
        //假設(shè)數(shù)據(jù)庫的用戶名和密碼  模擬數(shù)據(jù)庫
        //編寫shiro判斷邏輯,判斷用戶名和密碼
        //1.判斷用戶名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        User user = userService.findByMobil(token.getUsername());
        if(user==null){
            //用戶名不存在
            return null;  //shiro底層會(huì)拋出UnKnowAccountExceeption
        }
          //2 判斷密碼
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
}

配置攔截器信息

@Configuration
public class ShiroConfig {
    /**
     * 創(chuàng)建ShiroFilterFactoryBean
     */
           @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //設(shè)置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //添加Shrio內(nèi)置過濾器
            /**
             * Shiro內(nèi)置過濾器,可以實(shí)現(xiàn)權(quán)限相關(guān)的攔截器
             *     常用的過濾器:
             *        anon:無需認(rèn)證(登錄)可以訪問
             *        authc:必須認(rèn)證才可以訪問
             *        user:如果使用rememberMe的功能可以直接訪問
             *        perms:該資源必須得到資源權(quán)限才可以訪問
             *        role:該資源必須得到角色權(quán)限才可以訪問
             */
            Map<String ,String> filterMap = new LinkedHashMap<>();
//        filterMap.put("/add","authc");
//        filterMap.put("/update","authc");
            filterMap.put("/login","anon");
            filterMap.put("/tologin","anon");
            filterMap.put("/getinfo","anon");
            filterMap.put("/*","authc");
            //對(duì)用戶的修改功能進(jìn)行授權(quán)
            filterMap.put("/user/update","perms[user:update]");
            //授權(quán)過濾器
               // 注意:當(dāng)前授權(quán)攔截后,shiro會(huì)自動(dòng)跳轉(zhuǎn)到未授權(quán)頁面
            filterMap.put("/user/add","perms[user:add]");
            //設(shè)置未授權(quán)提示頁面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
        shiroFilterFactoryBean.setLoginUrl("/tologin");   //自定義設(shè)置攔截跳轉(zhuǎn)登錄頁面,默認(rèn)是login.jsp
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;

    }

    /**
     * 創(chuàng)建DefaultWebSecurityManager
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        //@Qualifier("userRealm")將userRealm注入當(dāng)前類
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //關(guān)聯(lián)realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }
    /**
     * 創(chuàng)建Realm
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }

    /**
     * 配置shiroDialect,用于thymeleaf和shiro標(biāo)簽配合使用
     */
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

controller

    @Autowired
    private UserService userService;

    @GetMapping("/noauth")
    public String noauth(){
        return "/noauth";
    }

    @PostMapping (value = "/login")
    public String login(String mobile,String password,Model model){
        /**
         * 使用Shiro編寫認(rèn)證操作
         */
        //1.獲取SUbject
        Subject subject = SecurityUtils.getSubject();
        //2分裝用戶數(shù)據(jù)
        UsernamePasswordToken token = new UsernamePasswordToken(mobile,password);
        //3.執(zhí)行登錄方法
        try {
            subject.login(token);
            //登錄成功
            return "redirect:getinfo";
        } catch (UnknownAccountException e) {
           // e.printStackTrace();
            //登錄失敗
            model.addAttribute("msg","用戶名不存在");
            return "login";
        }catch (IncorrectCredentialsException e) {
            //e.printStackTrace();
            //登錄失敗
            model.addAttribute("msg","密碼錯(cuò)誤");
            return "login";
        }
    }
}

前端頁面--結(jié)合動(dòng)態(tài)標(biāo)簽實(shí)現(xiàn)隱藏連接,有增加的用戶看不到修改的

<!DOCTYPE html>
<html xmlns:shiro="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8"/>
    <title>測(cè)試頁面</title>
</head>
<body>
用戶測(cè)試頁面
<div>
    <h3 th:text="${name}"></h3>
</div>
<hr/>
<div shiro:hasPermission="user:add">
進(jìn)入用戶添加功能: <a href="user/add">添加用戶</a><br/>
</div>
<div shiro:hasPermission="user:update">
進(jìn)入用戶更新功能: <a href="user/update">更新用戶</a><br/>
</div>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容