1. 程式人生 > 實用技巧 >基於Spring Boot整合shiro的基本使用

基於Spring Boot整合shiro的基本使用

1.引入依賴

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

2.瞭解shiro的三大物件(轉載至:https://blog.csdn.net/qq_41430393/article/details/87730198

):

1.Subject(主體)

應用程式碼的直接互動物件就是Subject,也就是說Shiro對外的核心API就是Subject,Subject代表了當前“使用者”,這個使用者不是指具體的某一個人,可以說與當前應用互動的任何東西都是Subject,與Subject的所有互動都會委託給SecurityManager來執行,可以理解為Subject只是一個充當門面的,真正的幕後老大是SecurityManager,SecurityManager才是實際的執行者。

2.SecurityManager(安全管理器)

所有與安全有關的操作都會與SecurityManager進行互動,並且SecurityManager管理者所有的Subject,可以看出它才是Shiro的核心,它負責與Shiro的其他元件進行互動,它相當於SpringMvc中的dispatcherServlet(前端控制器)的角色。

3.Realm

Shiro從Realm獲取安全資料(使用者、角色、許可權),就是說SecurityManager要驗證使用者身份,那麼它需要從Realm獲取相應的使用者進行比較以確定使用者身份是否合法,也需要從Realm獲取使用者的角色\許可權來判斷使用者是否能進行一系列操作。可以把Realm看作DataSource資料來源.

3.配置shiroConfig類以及shiroReaml類

shiroConfig類(將三大物件聯絡起來,配置需要攔截的頁面):

@Configuration //交由spring管理
public class shiroConfig {
    //自底向上建立,並繫結

    
//ShiroFilterFactoryBean,第三步 @Bean public ShiroFilterFactoryBean getFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //關聯安全管理器 bean.setSecurityManager(securityManager); //新增shiro的內建過濾器 /* anon:無需認證就可以訪問 authc:必須認證才能訪問 驗證密碼和使用者 user:必須擁有 記住我 功能才能用 perms:擁有對某個資源的許可權才能訪問 role:擁有某個角色許可權才能訪問 */ //使用map新增相應頁面的過濾 Map<String, String> filterMap=new LinkedHashMap<>(); //因為是鏈式過濾,所以得先過濾範圍小的 //不僅需要登陸還得擁有許可權才可訪問 //表示資料庫中user表中的欄位perm為user:update才表示有這個許可權訪問改路徑 filterMap.put("/user/update","perms[user:update]"); filterMap.put("/user/add","perms[user:add]"); //需要登陸即可訪問的頁面 filterMap.put("/user/*","authc"); //設定未登入時,進入需要許可權的頁面時,跳轉的登陸頁面 bean.setLoginUrl("/toLogin"); //設定許可權不足時跳轉的頁面 bean.setUnauthorizedUrl("/noAuth"); bean.setFilterChainDefinitionMap(filterMap); return bean; } //DefaultWebSecurityManager,第二步 @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("getRealm") shiroRealm shiroRealm){ DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(); //關聯realm securityManager.setRealm(shiroRealm); return securityManager; } //建立realm物件,第一步@Bean交由spring管理 @Bean public shiroRealm getRealm(){ return new shiroRealm(); } }

shiroReaml類(用於實現使用者認證和授權的操作)

//授權和認證都會經過此類
public class shiroRealm extends AuthorizingRealm {
    @Autowired
    userService service;

    //授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Subject subject = SecurityUtils.getSubject();//獲取當前使用者
        user currentUser = (user) subject.getPrincipal();//從當前使用者中取出Principal(認證時已儲存了user)
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//是AuthorizationInfo的實現類
        info.addStringPermission(currentUser.getPerm());//根據資料庫中的perm欄位新增相應的許可權
        return info;
    }


    //認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        user user = service.findByUsername(token.getUsername());
        //使用者名稱校驗,檢視是否存在使用者名稱
        if(user==null){
            return null;//返回null表示賬號不存在,會丟擲異常UnknownAccountException
        }
        //密碼校驗,shiro自帶檢驗
        //若是密碼錯誤會丟擲異常IncorrectCredentialsException
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
        //第一個引數是principal作用是傳遞資訊的,如認證完後可以將資料庫中查詢的user放進去,
        //供授權時,給相應的使用者新增相應資料庫中的許可權
    }
}

4.配置Controller的實現

@Controller
public class myController {

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

    @RequestMapping("/user/add")
    public String add(){
        return "user/add";
    }

    @RequestMapping("/user/update")
    public String update(){
        return "user/update";
    }

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

    @RequestMapping("/login")
    public String login(String username, String password, Model model){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        try {
            subject.login(token);// 該操作會將token轉至手寫的realm類中的doGetAuthenticationInfo方法中認證登陸
            return "index";
        }catch (UnknownAccountException e){//使用者名稱不存在
            model.addAttribute("msg","使用者名稱不存在");
            return "login";
        }catch (IncorrectCredentialsException e){//密碼不存在
            model.addAttribute("msg","密碼錯誤");
            return "login";
        }

    }

    @RequestMapping("/noAuth")
    @ResponseBody
    public String noAuth(){
        return "許可權不足!";
    }

    @RequestMapping("/logout")
    @ResponseBody
    public String logout(){
        SecurityUtils.getSubject().logout();//登出
        return "登出成功!";
    }
}