Spring Boot整合shiro

1灯抛、shiro是什么

用官方的話說Apache Shiro是一個功能強大且易于使用的Java安全框架福荸,它為開發(fā)人員提供了一種直觀而全面的解決方案喂分,用于身份驗證,授權(quán)块蚌,加密和會話管理闰非。
首先我們先看官方給出的Shiro外部結(jié)構(gòu)圖,看shiro是如何完成工作的:


官方結(jié)構(gòu)圖.png

shiro主要有三大功能模塊:

Subject:

應(yīng)用代碼直接交互的對象Subject峭范,也就是說Shiro的對外API核心就是Subject财松,代表了當(dāng)前的用戶,也不一定是一個具體的人纱控,也當(dāng)前應(yīng)用交互的任何東西都是Subject辆毡,與Subject的所有交互都會委托給SecurityManager,Subject其實就是一個門面甜害,SecurityManager才是實際的執(zhí)行者

SecurityManager:

安全管理器舶掖,即所有與安全有關(guān)的操作都會與SecurityManager交互,并且它管理著所有的Sbject唾那,它才是Shiro的核心访锻,負(fù)責(zé)與Shiro的其他組件進(jìn)行交互

Realms:

Shiro從Realm獲取安全數(shù)據(jù)(用戶褪尝,角色,權(quán)限)期犬,就是說SecurityManager要驗證用戶身份河哑,它就需要從Realm獲取相應(yīng)的用戶進(jìn)行比較,來確定用戶的身份是否合法龟虎,也需要用Realm得到用戶相應(yīng)的角色璃谨、權(quán)限,進(jìn)行驗證用戶的操作是否能夠進(jìn)行

2鲤妥、集成Shiro

1佳吞、導(dǎo)入jar包

在pom文件中添加shiro依賴

 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.6.0</version>
        </dependency>
2、編寫配置類

創(chuàng)建ShiroConfig類

@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean
    //DefaultWebSecurityManager
    //創(chuàng)建realm對象
}

這三個就對應(yīng)我們剛剛說的三個模塊棉安,然后就開始配置這三個對象底扳,我們先從realm開始配置,realm對象需要我們自己先定義贡耽,我們先新建一個ShiroRealm類然后繼承 AuthorizingRealm衷模,然后重寫他的方法,一個授權(quán)蒲赂,一個認(rèn)證

//自定義realm 需要繼承 AuthorizingRealm
public class ShiroRealm extends AuthorizingRealm {
    //授權(quán)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
    //認(rèn)證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        return null;
    }
}

然后返回ShiroConfig去創(chuàng)建realm對象

@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean
    //DefaultWebSecurityManager

    //創(chuàng)建realm對象
    @Bean
    public ShiroRealm shiroRealm(){
        return new ShiroRealm();
    }
}

這樣我們寫的對象就被spring托管了阱冶,接下來我們寫DefaultWebSecurityManager,因為DefaultWebSecurityManager需要Realm

@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean
    
    //DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //關(guān)聯(lián)realm
        securityManager.setRealm(shiroRealm);
        return securityManager;
    }

    //創(chuàng)建realm對象
    @Bean
    public ShiroRealm shiroRealm(){
        return new ShiroRealm();
    }
}

接下來寫ShiroFilterFactoryBean

@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager manager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //設(shè)置安全管理器
        bean.setSecurityManager(manager);
        return bean;
    }
    //DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //關(guān)聯(lián)realm
        securityManager.setRealm(shiroRealm);
        return securityManager;
    }

    //創(chuàng)建realm對象
    @Bean
    public ShiroRealm shiroRealm(){
        return new ShiroRealm();
    }
}

3滥嘴、設(shè)置過濾器

前面我們已經(jīng)把shiro初步集成了木蹬,接下來就需要配置過濾器

//ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager manager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //設(shè)置安全管理器
        bean.setSecurityManager(manager);
        /*
            添加shiro的內(nèi)置過濾器
            anon:  無需認(rèn)證就可訪問
            authc: 必須認(rèn)證才能訪問
            user:  必須擁有 記住我功能才可訪問
            perms: 擁有對某個資源的權(quán)限才能訪問
            role:  擁有某個角色權(quán)限才能訪問
         */
        Map<String,String>filterMap = new HashMap<>();
        filterMap.put("/version/*","authc");
        filterMap.put("/api/*","anon");
        bean.setFilterChainDefinitionMap(filterMap);
        //設(shè)置登錄請求
        bean.setLoginUrl("/home/toLogin");
        return bean;
    }

這樣配置的意思是路徑/version/是需要認(rèn)證才可訪問,/api/無需認(rèn)證就可訪問若皱,然后沒認(rèn)證的返回登錄頁面去認(rèn)證,接下來試試镊叁,在網(wǎng)頁中輸入網(wǎng)址


image.png

因為沒認(rèn)證過直接跳轉(zhuǎn)到了登錄頁面,這樣就算成功了


image.png

4走触、實現(xiàn)登錄功能

現(xiàn)在我們已經(jīng)成功攔截了我們設(shè)置的路徑意系,然后就要實現(xiàn)登錄通過認(rèn)證,首先寫一個用戶實體類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Admin {
    private Integer id;
    //用戶名稱
    private String name;
    //登錄帳號
    private String username;
    //登錄密碼
    private String password;
    //創(chuàng)建時間
    private Date createTime;
}

然后寫登錄方法

    @PostMapping("login")
    public String login(String adminName, String password, Model model) {
        Admin admin = adminMapper.searchByAccount(adminName);
        if (admin == null){
            model.addAttribute("error","帳號密碼錯誤");
            return "home/login";
        }
        if (!admin.getPassword().equals(password)){
            model.addAttribute("error","帳號密碼錯誤");
            return "home/login";
        }
        //獲取當(dāng)前用戶
        Subject subject = SecurityUtils.getSubject();
        //封裝用戶的登錄數(shù)據(jù)
        UsernamePasswordToken token = new UsernamePasswordToken(admin.getUsername(),admin.getPassword());
        try {
            subject.login(token);  //執(zhí)行登錄方法
            return "redirect:/version/list";
        } catch (Exception e){ 
            e.printStackTrace();
        }
        return "home/login";
    }

這樣我們在請求登錄請求后他會去執(zhí)行doGetAuthenticationInfo方法做認(rèn)證操作饺汹,那我們就去里面寫認(rèn)證操作

 //認(rèn)證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String adminName = token.getUsername();
        if (adminName != null && !adminName.equals("")){
            Admin admin = adminMapper.searchByAccount(adminName);
            if (admin != null){
                return new SimpleAuthenticationInfo(admin.getUsername(),admin.getPassword(),getName());
            }
        }
        return null;
    }

如果查詢數(shù)據(jù)庫沒有該用戶return null后會拋出一個UnknownAccountException異常蛔添,成功返回AuthenticationInfo的實現(xiàn)類
這樣我們就實現(xiàn)了登錄認(rèn)證功能

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市兜辞,隨后出現(xiàn)的幾起案子迎瞧,更是在濱河造成了極大的恐慌,老刑警劉巖逸吵,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凶硅,死亡現(xiàn)場離奇詭異,居然都是意外死亡扫皱,警方通過查閱死者的電腦和手機足绅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門捷绑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人氢妈,你說我怎么就攤上這事粹污。” “怎么了首量?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵壮吩,是天一觀的道長。 經(jīng)常有香客問我加缘,道長鸭叙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任拣宏,我火速辦了婚禮沈贝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘勋乾。我一直安慰自己缀程,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布市俊。 她就那樣靜靜地躺著,像睡著了一般滤奈。 火紅的嫁衣襯著肌膚如雪摆昧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天蜒程,我揣著相機與錄音绅你,去河邊找鬼。 笑死昭躺,一個胖子當(dāng)著我的面吹牛忌锯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播领炫,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼偶垮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了帝洪?” 一聲冷哼從身側(cè)響起似舵,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎葱峡,沒想到半個月后砚哗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡砰奕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年蛛芥,在試婚紗的時候發(fā)現(xiàn)自己被綠了提鸟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡仅淑,死狀恐怖称勋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漓糙,我是刑警寧澤铣缠,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站昆禽,受9級特大地震影響蝗蛙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜醉鳖,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一捡硅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盗棵,春花似錦壮韭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞭恰,卻和暖如春屯曹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惊畏。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工恶耽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人颜启。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓偷俭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缰盏。 傳聞我的和親對象是個殘疾皇子涌萤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350