日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

Shiro和SpringSecurity

作者:l1050188952 更新時(shí)間: 2022-09-25 編程語(yǔ)言

一、Shiro

????????Shiro是一個(gè)強(qiáng)大而靈活的開(kāi)源安全框架,,執(zhí)行身份驗(yàn)證、授權(quán)、密碼和會(huì)話管理。使用Shiro易于理解的API,可以快速、輕松地獲得任何應(yīng)用程序,從最小的移動(dòng)應(yīng)用程序到最大的網(wǎng)絡(luò)和企業(yè)應(yīng)用程序。(和Spring?Security,Shiro在保持強(qiáng)大功能的同時(shí),還在簡(jiǎn)單性和靈活性方面擁有巨大優(yōu)勢(shì))

三個(gè)核心組件:Subject, SecurityManager 和 Realms

Subject:是“當(dāng)前操作用戶”。但是,在Shiro中,Subject這一概念并不僅僅指人,也可以是第三方進(jìn)程、后臺(tái)帳戶(Daemon?Account)或其他類(lèi)似事物。它僅僅意味著“當(dāng)前跟軟件交互的東西”。Subject代表了當(dāng)前用戶的安全操作,SecurityManager則管理所有用戶的安全操作。

SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通過(guò)SecurityManager來(lái)管理內(nèi)部組件實(shí)例,并通過(guò)它來(lái)提供安全管理的各種服務(wù)。

Realm:?Realm充當(dāng)了Shiro與應(yīng)用安全數(shù)據(jù)間的“橋梁”或者“連接器”。也就是說(shuō),當(dāng)對(duì)用戶執(zhí)行認(rèn)證(登錄)和授權(quán)(訪問(wèn)控制)驗(yàn)證時(shí),Shiro會(huì)從應(yīng)用配置的Realm中查找用戶及其權(quán)限信息。

從這個(gè)意義上講,Realm實(shí)質(zhì)上是一個(gè)安全相關(guān)的DAO:它封裝了數(shù)據(jù)源的連接細(xì)節(jié),并在需要時(shí)將相關(guān)數(shù)據(jù)提供給Shiro。當(dāng)配置Shiro時(shí),你必須至少指定一個(gè)Realm,用于認(rèn)證和(或)授權(quán)。配置多個(gè)Realm是可以的,但是至少需要一個(gè)。

Shiro內(nèi)置了可以連接大量安全數(shù)據(jù)源(又名目錄)的Realm,如LDAP、關(guān)系數(shù)據(jù)庫(kù)(JDBC)、類(lèi)似INI的文本配置資源以及屬性文件等。如果系統(tǒng)默認(rèn)的Realm不能滿足需求,你還可以插入代表自定義數(shù)據(jù)源的自己的Realm實(shí)現(xiàn)。

實(shí)現(xiàn)代碼:

坐標(biāo):

<!--shiro和spring整合-->
    <dependency>
         <groupId>org.apache.shiro</groupId>
         <artifactId>shiro-spring</artifactId>
         <version>1.3.2</version>
    </dependency>
<!--shiro核心包-->
     <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
      </dependency>

創(chuàng)建realm

@Configuration
public class ShiroConfiguration {
 
    //1.創(chuàng)建realm
    @Bean
    public CustomRealm getRealm() {
        return new CustomRealm();
    }
 
    //2.創(chuàng)建安全管理器
    @Bean
    public SecurityManager getSecurityManager(CustomRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }
 
    //3.配置shiro的過(guò)濾器工廠再web程序中,shiro進(jìn)行權(quán)限控制全部是通過(guò)一組過(guò)濾器集合進(jìn)行控制
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //1.創(chuàng)建過(guò)濾器工廠
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.設(shè)置安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置(跳轉(zhuǎn)登錄頁(yè)面,為授權(quán)跳轉(zhuǎn)的頁(yè)面)
        filterFactory.setLoginUrl("/autherror");//跳轉(zhuǎn)url地址
        //4.設(shè)置過(guò)濾器集合
        //key = 攔截的url地址
        //value = 過(guò)濾器類(lèi)型
        Map<String,String> filterMap = new LinkedHashMap<>();
 
        filterMap.put("/login","anon");//當(dāng)前請(qǐng)求地址可以匿名訪問(wèn)
        filterMap.put("/user/**","authc");//當(dāng)前請(qǐng)求地址必須認(rèn)證之后可以訪問(wèn)
 
        //在過(guò)濾器工程內(nèi)設(shè)置過(guò)濾器
        filterFactory.setFilterChainDefinitionMap(filterMap);
 
        return filterFactory;
    }
 
    //開(kāi)啟對(duì)shior注解的支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
    //啟對(duì)shior注解的支持2
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator app=new DefaultAdvisorAutoProxyCreator();
        app.setProxyTargetClass(true);
        return app;
    }
 
 
 
 
 
 
}

認(rèn)證和授權(quán)方法

public class CustomRealm extends AuthorizingRealm {
 
    public void setName(String name) {
        super.setName("customRealm");
    }
 
    @Autowired
    private UserService userService;
    /**
     * 授權(quán)方法
     *      操作的時(shí)候,判斷用戶是否具有響應(yīng)的權(quán)限
     *          一定先認(rèn)證再授權(quán)
     *          先認(rèn)證 -- 安全數(shù)據(jù)
     *          再授權(quán) -- 根據(jù)安全數(shù)據(jù)獲取用戶具有的所有操作權(quán)限
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.獲取已認(rèn)證的用戶數(shù)據(jù)
        User user = (User) principalCollection.getPrimaryPrincipal();//得到唯一的安全數(shù)據(jù)
        //2.根據(jù)用戶數(shù)據(jù)獲取用戶的權(quán)限信息(所有角色,所有權(quán)限)
        Set<String> roles = new HashSet<>();//所有角色
        Set<String> perms = new HashSet<>();//所有權(quán)限
        for (Role role : user.getRoles()) {
            roles.add(role.getName());
            for (Permission perm : role.getPermissions()) {
                perms.add(perm.getCode());
            }
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(perms);
        info.setRoles(roles);
        return info;
    }
    /**
     * 認(rèn)證方法
     *  參數(shù):傳遞的用戶名密碼
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.獲取登錄的用戶名密碼(token)
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String username = upToken.getUsername();//用戶錄入的賬號(hào)
        //2.根據(jù)用戶名查詢(xún)數(shù)據(jù)庫(kù)
        //mybatis情景下:user對(duì)象中包含ID,name,pwd(匿名)
        //JPA情景下:user對(duì)象中包含ID,name,pwd(匿名),set<角色>,set<權(quán)限>
        User user = userService.findByName(username);
        //3.判斷用戶是否存在或者密碼是否一致
        if(user != null) {
            //4.如果一致返回安全數(shù)據(jù)
            //構(gòu)造方法:安全數(shù)據(jù),密碼(匿名),混淆字符串(salt),realm域名
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
            return info;
        }
        //5.不一致,返回null(拋出異常)
        return null;
    }
 
 
    /**
    *  自定義密碼比較器
    */
    @PostConstruct
    public void initCredentialsMatcher() {
        //指定密碼算法
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
        //指定迭代次數(shù)
        hashedCredentialsMatcher.setHashIterations(DigestsUtil.COUNTS);
        //生效密碼比較器
        setCredentialsMatcher(hashedCredentialsMatcher);
    }
 
 
 
}

密碼加密

public class DigestsUtil {
 
    //加密方式
    public static final String SHA1 = "SHA-1";
 
    //循環(huán)次數(shù)
    public static final Integer COUNTS =520;
 
    public static String sha1(String input, String salt) {
       return new SimpleHash(SHA1, input, salt,COUNTS).toString();
    }
 
 
   // 隨機(jī)獲得salt字符串
    public static String generateSalt(){
        SecureRandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
        return randomNumberGenerator.nextBytes().toHex();
    }
 
 
   //生成密碼字符密文和salt密文
    
    public static Map<String,String> entryptPassword(String passwordPlain) {
       Map<String,String> map = new HashMap<>();
       String salt = generateSalt();
       String password =sha1(passwordPlain,salt);
       map.put("salt", salt);
       map.put("password", password);
       return map;
    }
}

二、Spring?Security

????????Spring?Security是一個(gè)能夠?yàn)榛?span style="color:#ff9900;">Spring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問(wèn)控制解決方案的安全框架。它提供了一組可以在Spring應(yīng)用上下文中配置的Bean,充分利用了Spring?IoC,DI(控制反轉(zhuǎn)Inversion?of?Control?,DI:Dependency?Injection?依賴(lài)注入)和AOP(面向切面編程)功能,為應(yīng)用系統(tǒng)提供聲明式的安全訪問(wèn)控制功能,減少了為企業(yè)系統(tǒng)安全控制編寫(xiě)大量重復(fù)代碼的工作。(除了不能脫離Spring,shiro的功能它都有。而且Spring Security對(duì)Oauth、OpenID也有支持,Shiro則需要自己手動(dòng)實(shí)現(xiàn)。Spring Security的權(quán)限細(xì)粒度更高


實(shí)現(xiàn)代碼:坐標(biāo)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
@Configuration    //就相當(dāng)于springmvc.xml文件
public class WebConfig implements WebMvcConfigurer {
 
 
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //訪問(wèn)登陸頁(yè)面,安全框架所提供的
        registry.addViewController("/loginPage").setViewName("login");
    }
 
}

安全攔截機(jī)制(重點(diǎn))

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
    /**
     * 定義用戶信息服務(wù)(查詢(xún)用戶信息)
     * 方式1:通過(guò)內(nèi)存定義
     * 方式2:查詢(xún)數(shù)據(jù)庫(kù)
    */
 
    @Bean    //密碼編碼器
    public PasswordEncoder passwordEncoder(){
        return  new BCryptPasswordEncoder();
    }
 
    //安全攔截機(jī)制(最重要)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()         //關(guān)閉csrf防火墻,避免csrf現(xiàn)象
                .authorizeRequests()  //所有請(qǐng)求
 
               .antMatchers("/r/r1").hasAuthority("p1")    
                //訪問(wèn)/r/r1資源的 url需要擁有p1權(quán)限。
 
               .antMatchers("/r/r2").hasAuthority("p2") 
                //訪問(wèn)/r/r2資源的 url需要擁有p2權(quán)限
 
                .antMatchers("/r/**").authenticated()  
                 //所有/r/**的請(qǐng)求必須認(rèn)證通過(guò)
 
                .anyRequest().permitAll()              
                 //除了/r/**,其它的請(qǐng)求可以訪問(wèn)
                .and()
                .formLogin()
                .loginPage("/loginPage")                    //允許表單登錄
                .loginProcessingUrl("/doLogin")              //登錄的提交接口
                .successForwardUrl("/login-success");   //自定義登錄成功的頁(yè)面地址
 
    }
}

啟動(dòng)類(lèi)注解

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
@ServletComponentScan
public class SecuritySpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(SecuritySpringBootApp.class,args);
    }

授權(quán)注解

    @GetMapping(value = "/r/r1")
    @PreAuthorize("hasAuthority('user-find')")//擁有p1權(quán)限才可以訪問(wèn)
    public String r1(){
        return " 訪問(wèn)資源1";
    }

總結(jié):? ? ?

相同點(diǎn):
1.其核心都是一組過(guò)濾器鏈。
2.認(rèn)證功能
3.授權(quán)功能
4.加密功能
5.會(huì)話管理
6.緩存支持
7.rememberMe功能

區(qū)別:
1.Spring?Security是一個(gè)重量級(jí)的安全管理框架;Shiro則是一個(gè)輕量級(jí)的安全管理框架
2.Spring?Security?基于Spring開(kāi)發(fā),項(xiàng)目若使用Spring作為基礎(chǔ),配合Spring?Security?做權(quán)限更便捷,而Shiro需要和Spring?進(jìn)行整合開(kāi)發(fā);
3.Spring?Security?功能比Shiro更加豐富些,例如安全維護(hù)方面;
4.Spring?Security?社區(qū)資源相對(duì)于Shiro更加豐富;
5.Shiro?的配置和使用比較簡(jiǎn)單,Spring?Security?上手復(fù)雜些;
6.Shiro?依賴(lài)性低,不需要任何框架和容器,可以獨(dú)立運(yùn)行,?Spring?Security依賴(lài)Spring容器;
7.Shiro?不僅僅可以使用在web中,它可以工作在任何應(yīng)用環(huán)境中。在集群會(huì)話時(shí)Shiro最重要的一個(gè)好處或許就是它的會(huì)話是獨(dú)立于容器的;

Shiro有很多地方都比Spring Security方便簡(jiǎn)單直接,比起Spring Security的龐大模式更容易理解和切入一些,而Spring Security比Shiro功能上要多一點(diǎn),再就是和spring框架的無(wú)縫對(duì)接,比如支持spel等,有時(shí)候比Shiro更方便靈活。

原文鏈接:https://blog.csdn.net/l1050188952/article/details/126693947

欄目分類(lèi)
最近更新