最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot下使用shiro自定義filter的個(gè)人經(jīng)驗(yàn)分享

 更新時(shí)間:2021年09月16日 16:16:36   作者:追逐夢(mèng)想永不停  
這篇文章主要介紹了springboot下使用shiro自定義filter的個(gè)人經(jīng)驗(yàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

在springboot中使用shiro,由于沒(méi)有了xml配置文件,因此使用的方法與spring中有些區(qū)別。在踩了無(wú)數(shù)個(gè)坑后,在此將springboot下使用shiro的步驟總結(jié)如下。

由于本人對(duì)shiro的了解不是很深入,在實(shí)現(xiàn)了工作需求后就沒(méi)有繼續(xù)研究了,因此可能存在遺漏的地方或有錯(cuò)誤的地方,還請(qǐng)多包涵。

目標(biāo)

  • 在springboot中使用shiro
  • 1.實(shí)現(xiàn)用戶(hù)的登錄驗(yàn)證
  • 2.對(duì)于一些指定的url使用自定義的filter驗(yàn)證方式(不再使用shiro的realm驗(yàn)證)

步驟

1.在pom.xml中添加shiro的依賴(lài)

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

2.創(chuàng)建ShiroRealm.java

繼承AuthorizingRealm類(lèi),重寫(xiě)登錄認(rèn)證方法與授權(quán)方法

import User;
import UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired; 
import java.util.ArrayList;
import java.util.List;
 
public class ShiroRealm extends AuthorizingRealm {
    //自己編寫(xiě)的service,注入,執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)方法用
    @Autowired
    private UserService userService;
    //認(rèn)證.登錄
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;//獲取用戶(hù)輸入的token
        String username = utoken.getUsername();
        //這個(gè)User對(duì)象為自定義的JavaBean,使用userService從數(shù)據(jù)庫(kù)中得到User對(duì)象(包含用戶(hù)名、密碼、權(quán)限3個(gè)字段)
        User user = userService.findUserByUserName(username);
        return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());//放入shiro.調(diào)用CredentialsMatcher檢驗(yàn)密碼
    }
    //授權(quán)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        User user=(User) principal.fromRealm(this.getClass().getName()).iterator().next();//獲取session中的用戶(hù)
        List<String> permissions=new ArrayList<>();
        //使用自定義的user對(duì)象獲得權(quán)限字段,string類(lèi)型,裝入集合
        permissions.add(user.getRole());
 
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions);//將權(quán)限放入shiro中.(我的代碼中其實(shí)沒(méi)有用到權(quán)限相關(guān))
        return info;
    }
}

3.創(chuàng)建ShiroConfiguration.java

使用@Configuration注解,是shiro的配置類(lèi),類(lèi)似xml

import java.util.LinkedHashMap;
import java.util.Map; 
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 
import javax.servlet.Filter;
 
@Configuration
public class ShiroConfiguration { 
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
        // 必須設(shè)置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
 
        /*重要,設(shè)置自定義攔截器,當(dāng)訪(fǎng)問(wèn)某些自定義url時(shí),使用這個(gè)filter進(jìn)行驗(yàn)證*/
        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        //如果map里面key值為authc,表示所有名為authc的過(guò)濾條件使用這個(gè)自定義的filter
        //map里面key值為myFilter,表示所有名為myFilter的過(guò)濾條件使用這個(gè)自定義的filter,具體見(jiàn)下方
        filters.put("myFilter", new MyFilter());
        shiroFilterFactoryBean.setFilters(filters);
        /*---------------------------------------------------*/
 
        //攔截器
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        //配置退出過(guò)濾器,其中的具體的退出代碼Shiro已經(jīng)替我們實(shí)現(xiàn)了
        filterChainDefinitionMap.put("/logout", "logout");
        //  anon:所有url都都可以匿名訪(fǎng)問(wèn);
        //  authc: 需要認(rèn)證才能進(jìn)行訪(fǎng)問(wèn);
        //  user:配置記住我或認(rèn)證通過(guò)可以訪(fǎng)問(wèn);
        //放開(kāi)靜態(tài)資源的過(guò)濾
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        //放開(kāi)登錄url的過(guò)濾
        filterChainDefinitionMap.put("/loginController", "anon");
        ///
        //對(duì)于指定的url,使用自定義filter進(jìn)行驗(yàn)證
        filterChainDefinitionMap.put("/targetUrl", "myFilter");
        //可以配置多個(gè)filter,用逗號(hào)分隔,按順序過(guò)濾,下方表示先通過(guò)自定義filter的驗(yàn)證,再通過(guò)shiro默認(rèn)過(guò)濾器的驗(yàn)證
        //filterChainDefinitionMap.put("/targetUrl", "myFilter,authc");
        ///
        //過(guò)濾鏈定義,從上向下順序執(zhí)行,一般將 /**放在最為下邊
        //url從上向下匹配,當(dāng)條件匹配成功時(shí),就會(huì)進(jìn)入指定filter并return(不會(huì)判斷后續(xù)的條件),因此這句需要在最下邊
        filterChainDefinitionMap.put("/**", "authc");
 
        //如果不設(shè)置默認(rèn)會(huì)自動(dòng)尋找Web工程根目錄下的"/login.jsp"頁(yè)面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登錄成功后要跳轉(zhuǎn)的鏈接
        shiroFilterFactoryBean.setSuccessUrl("/loginSuccess");
        // 未授權(quán)界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/403"); 
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 
        return shiroFilterFactoryBean;
    }
 
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        return securityManager;
    }
    //配置核心安全事務(wù)管理器
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm) {
        DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
        manager.setRealm(shiroRealm);
        return manager;
    }
    //配置自定義的權(quán)限登錄器
    @Bean(name="shiroRealm")
    public ShiroRealm shiroRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        ShiroRealm shiroRealm=new ShiroRealm();
        shiroRealm.setCredentialsMatcher(matcher);
        return shiroRealm;
    }
    //配置自定義的密碼比較器
    @Bean(name="credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
        return new CredentialsMatcher();
    }
}

4.創(chuàng)建自定義的過(guò)濾器MyFilter.java

繼承AccessControlFilter類(lèi),在步驟3中使用

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set; 
public class MyFilter extends AccessControlFilter {
    private static Logger log = LoggerFactory.getLogger(MyFilter.class);
 
    //判斷是否攔截,false為攔截,true為允許
    @Override
    public boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object object) throws Exception {
        Subject subject = getSubject(req,resp);
        String url = getPathWithinApplication(req);
        log.info("當(dāng)前用戶(hù)正在訪(fǎng)問(wèn)的url為 " + url);
        log.info("subject.isPermitted(url);"+subject.isPermitted(url));
        //可自行根據(jù)需要判斷是否攔截,可以獲得subject判斷用戶(hù)權(quán)限,也可以使用req獲得請(qǐng)求頭請(qǐng)求體信息
        //return true;
        return false;        
    }
 
    //上面的方法返回false后(被攔截),會(huì)進(jìn)入這個(gè)方法;這個(gè)方法返回false表示處理完畢(不放行);返回true表示需要繼續(xù)處理(放行)
    @Override
    public boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {     
        //從req中獲得的值,也可以自己使用其它判斷是否放行的方法
        String username = request.getParameter("name");
        String password = request.getParameter("password");
        //創(chuàng)建token對(duì)象
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            //使用subject對(duì)象的login方法驗(yàn)證該token能否登錄(使用方法2中的shiroRealm.java中的方法驗(yàn)證)
            subject.login(usernamePasswordToken);
        } catch (Exception e) {
            //log.info("登陸失敗");
            //log.info(e.getMessage());
            return false;
        }
        //log.info("登陸成功");
        return true;
    }
}

5.步驟3中使用了自定義密碼驗(yàn)證的方式

因此需要?jiǎng)?chuàng)建類(lèi)CredentialsMatcher.java(與步驟3中的名稱(chēng)對(duì)應(yīng)),繼承SimpleCredentialsMatcher類(lèi)

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; 
public class CredentialsMatcher extends SimpleCredentialsMatcher {
 
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;
        //獲得用戶(hù)輸入的密碼:(可以采用加鹽(salt)的方式去檢驗(yàn))
        String inPassword = new String(utoken.getPassword());
        //獲得數(shù)據(jù)庫(kù)中的密碼
        String dbPassword=(String) info.getCredentials();
        //進(jìn)行密碼的比對(duì)
        return this.equals(inPassword, dbPassword);
    }
}

6.步驟3中放開(kāi)了對(duì)登錄頁(yè)/loginController的過(guò)濾

因此我增加了一個(gè)ShiroController.java類(lèi)

import User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; 
import javax.servlet.http.HttpSession;
 
@Controller
public class ShiroController {
    @RequestMapping("/")
    public String loginPage() {
        return "login";
    }
    @RequestMapping("/login")
    public String login() {
        return "login";
    }
    @RequestMapping("/loginController")
    public String loginUser(String username,String password,HttpSession session) {
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(usernamePasswordToken);   //完成登錄
            //自定義的JavaBean,用于保存用戶(hù)名、密碼、權(quán)限3個(gè)字段
            User user=(User) subject.getPrincipal();
            //可選,可放入session,以備后續(xù)使用
            session.setAttribute("user", user);
            //跳轉(zhuǎn)到登錄成功頁(yè)(controller)
            return "forward:/loginSuccess";
        } catch(Exception e) {
            //登錄失敗,跳轉(zhuǎn)回登錄頁(yè)(html)
            return "login";
        } 
    }
    @RequestMapping("/logOut")
    public String logOut(HttpSession session) {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        //session.removeAttribute("user");
        return "login";
    }
}

個(gè)人經(jīng)驗(yàn)

1.shiro配置類(lèi)中的url攔截的執(zhí)行順序?yàn)閺纳系较拢绻鹵rl匹配到一個(gè)規(guī)則,則會(huì)跳出匹配方法,忽略后續(xù)的匹配規(guī)則(相當(dāng)于return)。

2.shiro使用自定義filter時(shí),最好繼承shiro的filter,不要直接繼承Filter類(lèi)。

3.shiro使用自定義filter時(shí),map集合的key配置為"authc"、value配置為"new MyFilter()"時(shí),表示對(duì)配置為authc的url使用自定義filter進(jìn)行攔截,而不會(huì)使用ShiroRealm中的驗(yàn)證方法驗(yàn)證(可能是將shiro默認(rèn)的authc的攔截器覆蓋了);因此最好將key配置為其它自定義的字符串,將部分url的攔截規(guī)則設(shè)置為使用自定義filter攔截即可(如果仍想使用shiro默認(rèn)的攔截器,可用逗號(hào)連接"authc")。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中的StringUtils引入及使用示例教程

    Java中的StringUtils引入及使用示例教程

    這篇文章主要介紹了Java中的StringUtils引入及使用示例教程,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),介紹了java中StringUtils用法,感興趣的朋友跟隨小編一起看看吧
    2023-01-01
  • SpringBoot如何集成Token

    SpringBoot如何集成Token

    文章介紹了如何使用jjwt插件實(shí)現(xiàn)Token的生成和校驗(yàn),該插件可以直接與SpringBoot集成,Token由三部分組成,分別是header、payload和signature,通過(guò)在請(qǐng)求頭中傳遞Token,后端可以驗(yàn)證其合法性,從而提高安全性
    2025-01-01
  • SpringCloudGateway?Nacos?GitlabRunner全自動(dòng)灰度服務(wù)搭建發(fā)布

    SpringCloudGateway?Nacos?GitlabRunner全自動(dòng)灰度服務(wù)搭建發(fā)布

    這篇文章主要為大家介紹了SpringCloudGateway?Nacos?GitlabRunner全自動(dòng)灰度服務(wù)搭建和發(fā)布實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Java實(shí)現(xiàn)簡(jiǎn)單QQ聊天工具

    Java實(shí)現(xiàn)簡(jiǎn)單QQ聊天工具

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單QQ聊天工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • Java匿名內(nèi)部類(lèi)導(dǎo)致內(nèi)存泄露的原因與解決方案詳解

    Java匿名內(nèi)部類(lèi)導(dǎo)致內(nèi)存泄露的原因與解決方案詳解

    這篇文章主要為大家詳細(xì)介紹了Java因?yàn)槟涿麅?nèi)部類(lèi)導(dǎo)致內(nèi)存泄露的原因以及其解決方案,文中的示例代碼講解詳細(xì),希望對(duì)大家有所幫助
    2022-11-11
  • 淺談為什么重寫(xiě)equals()就要重寫(xiě)hashCode()

    淺談為什么重寫(xiě)equals()就要重寫(xiě)hashCode()

    困擾我很久的問(wèn)題,一直不明白為什么重寫(xiě)equals()方法的時(shí)候要重寫(xiě)hashCode()方法,這次總算弄明白了,作此分享,感興趣的可以了解一下
    2021-10-10
  • spring-boot-maven-plugin:unknown的完美解決方法

    spring-boot-maven-plugin:unknown的完美解決方法

    這篇文章主要介紹了spring-boot-maven-plugin:unknown的完美解決方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • JVM知識(shí)總結(jié)之垃圾收集算法

    JVM知識(shí)總結(jié)之垃圾收集算法

    本博客為讀書(shū)筆記,讀的是《深入理解Java虛擬機(jī)》一書(shū),在看這個(gè)書(shū)的時(shí)候,最大的一個(gè)感受便是“當(dāng)初怎么就沒(méi)有好好學(xué)習(xí)操作系統(tǒng)呢,不然也不會(huì)有這么多看的云里霧里的地方了”,不過(guò)那都是過(guò)去的事了,學(xué)習(xí)最好的時(shí)刻便是現(xiàn)在,需要的朋友可以參考下
    2021-06-06
  • 詳解java注解相關(guān)知識(shí)

    詳解java注解相關(guān)知識(shí)

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著java注解的使用展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java main 方法面試題的詳細(xì)整理

    Java main 方法面試題的詳細(xì)整理

    這篇文章主要介紹了Java main 方法面試題的詳細(xì)整理的相關(guān)資料,這里介紹了10個(gè)經(jīng)典面試題的方法,需要的朋友可以參考下
    2017-09-09

最新評(píng)論

九龙坡区| 宝鸡市| 安多县| 三穗县| 承德市| 迁安市| 天台县| 农安县| 报价| 河东区| 西昌市| 廉江市| 开化县| 许昌县| 永年县| 西畴县| 延寿县| 油尖旺区| 宿州市| 布尔津县| 仁怀市| 乌兰浩特市| 涪陵区| 平泉县| 许昌县| 金门县| 汝南县| 苍溪县| 洞口县| 武义县| 唐海县| 拉孜县| 稻城县| 苍南县| 桦甸市| 澄江县| 永仁县| 新化县| 新乐市| 惠州市| 乌鲁木齐县|