编程知识 cdmana.com

Cadre de sécurité Shiro - [QUICKstart, login Block, User Authentication, request Authorization]

Table des matières

Un.、ShiroIntroduction:

shiroFonction:

ShiroArchitecture(Extérieur)

ShiroArchitecture(Interne)

2.、Démarrage rapide

1.Cas de copie

 2.Code d'analyse

Trois、SpringBoot Intégration Shiro

1. Écrire un environnement de test

2.Utiliser

1. Interception de connexion

 2.Authentification de l'utilisateur

Quatre、ShiroIntégrationMybatis

Cinq、 Demande d'autorisation de mise en oeuvre

Six、ShiroIntégrationThymeleaf


Un.、ShiroIntroduction:

Apache ShiroC'est unJavaSécurité(Autorité)Cadre.
Shiro Il est très facile de développer assez de bonnes Applications,Non seulement il peut être utiliséJavaSEEnvironnement,Peut également être utiliséJavaEEEnvironnement.ShiroÇa peut être fait,Certification,Autorisation,Cryptage,Gestion des sessions,WebIntégration,Cache, etc..
Adresse du site officiel:Apache Shiro | Simple. Java. Security.

shiroFonction:

Authentication:Authentification de l'identité、Connexion,Vérifier que l'utilisateur a l'identité appropriée;
Authorization:Autorisation,C'est - à - dire la vérification des droits,Vérifier qu'un utilisateur authentifié a une autorisation,C'est - à - dire déterminer ce que l'utilisateur peut faire,Par exemple::Vérifier qu'un utilisateur a un rôle,Ou vérifier à grain fin qu'un utilisateur a des permissions sur une ressource!
Session Manager:Gestion des sessions,C'est - à - dire que l'utilisateur se connecte pour la première fois,Avant de quitter,Toutes ses informations sont dans la session;Les sessions peuvent être ordinairesJavaSEEnvironnement,C'est possible.WebEnvironnement;
Cryptography:Cryptage,Protection de la sécurité des données,Si le chiffrement du mot de passe est stocké dans la base de données,Au lieu d'un stockage en texte clair;Web Support: WebSoutien,Peut être facilement intégréWebEnvironnement;
Caching:Cache,Par exemple, après la connexion de l'utilisateur,Informations sur l'utilisateur,Rôles détenus、Les permissions ne doivent pas être vérifiées à chaque fois,Cela augmente l'efficacité
Concurrency: ShiroPrise en charge de la validation simultanée pour les applications multithreadées,C'est - à - dire:,Si vous ouvrez un autre thread dans un thread,Peut propager automatiquement les permissions dans le passé
Testing:Fournir un soutien aux essais;
Run As:Permettre à un utilisateur de prétendre être un autre utilisateur(S'ils le permettent)Accès en tant que;
Remember Me:Souviens - toi de moi.,C'est une fonction très courante,C'est - à - dire après une connexion,Ne vous connectez pas si vous revenez la prochaine fois

ShiroArchitecture(Extérieur)

De l'extérieurShiro, C'est - à - dire observer comment utiliser du point de vue de l'application shiroAchèvement des travaux:

subject:Les objets avec lesquels le Code d'application interagit directement sont:Subject,C'est - à - direShiroDe l'extérieurAPILe cœur estSubject,Subject Représente l'utilisateur actuel , Cet utilisateur n'est pas nécessairement une personne spécifique ,Tout ce qui interagit avec l'application actuelle estSubject,Comme un crawler Web,Robots, etc,AvecSubjectToutes les interactions deSecurityManager; Subject En fait, c'est une façade ,SecurityManageerC'est le vrai exécuteur
SecurityManager: Gestionnaire de la sécurité,C'est - à - dire que toutes les opérations liées à la sécurité sont liéesSercurityManagerInteraction, Et il gère tout Subject,On peut voir que c'estShiroAu cœur de,Il est chargé deShiroD'autres composants interagissent,C'est l'équivalentSpringMVCDe
DispatcherServletLe rôle de
Realm: ShiroDeRealmAccès aux données de sécurité((Comme l'utilisateur,Rôle,Autorité),C'est - à - direSecurityManagerPour vérifier l'identité de l'utilisateur,Il faut doncRealm Obtenir les utilisateurs appropriés pour la comparaison,Pour déterminer si l'identité de l'utilisateur est légale;Il faut aussiRealmObtenir le rôle correspondant de l'utilisateur、Autorité,Effectuer la vérification que les actions de l'utilisateur peuvent être effectuées,Tu peux mettreRealmVoirDataSource;

ShiroArchitecture(Interne)

subject:Tout ce qui peut interagir avec l'application'Utilisateurs';
Security Manager:équivalent àSpringMVCDansDispatcherServlet;- Oui.ShiroLe cœur,Toutes les interactions spécifiques passent parSecurity ManagerPour contrôler,Il est géré parSubject,Et être responsable de la certification,Autorisation,Session,Gestion du cache.

Authenticator:ResponsableSubjectCertification, C'est un point d'extension ,Peut être personnalisé;Les politiques d'authentification peuvent être utilisées(AuthenticationStrategy),Dans quelles circonstances l'authentification de l'utilisateur a - t - elle été acceptée?;
Authorizer: Authorizer,Contrôleur d'accès,Utilisé pour déterminer si le principal a l'autorisation d'effectuer les opérations correspondantes; C'est - à - dire contrôler l'accès de l'utilisateur aux fonctions de l'application ;
Realm:Peut avoir un ou plusieursrealm,Peut être considéré comme une source de données d'entité sécurisée,C'est - à - dire pour obtenir une entité sécurisée,Ça marcheDBCRéalisation,Ou une implémentation de mémoire, etc.,Fourni par l'utilisateur; Donc, en général, vous devez mettre en œuvre votre propre realm
SessionManager: GestionSessionComposantes du cycle de vie,EtShiroPas seulement pourWebEnvironnement,Peut également être utilisé dans des applications normalesJavaSEDans l'environnement
CacheManager:Contrôleur de cache,Pour gérer comme un utilisateur,Rôle,Mise en cache des permissions, etc.; Parce que ces données sont en grande partie très limitées , Une fois mis en cache, vous pouvez améliorer les performances d'accès ;
Cryptography:Module mot de passe,ShiroAmélioration de certains composants de chiffrement communs pour le chiffrement par mot de passe,Décryptage, etc

2.、Démarrage rapide

1.Cas de copie

1. Suivez les conseils du site officiel pour trouver Cas de démarrage rapide              GitHubAdresse:shiro/samples/quickstart/

2.Créer un nouveau Maven Ingénierie, Supprimer src Table des matières, En tant que projet parent

3. Créer un nouveau Maven Module

4. Copier le cas de démarrage rapide POM.xml Dépendances dans le fichier 

<dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.1</version>
        </dependency>

        <!-- configure logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.29</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.29</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

5. Prenez le cas de démarrage rapide resource En baslog4j.propertiesCopier

6.Copiezshiro.iniDocumentation

7.CopiezQuickstart.javaDocumentation

8.Démarrage de l'opérationQuickstart.java

 2.Code d'analyse

public class Quickstart {
    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
    public static void main(String[] args) {
        //Mode usine,Adoptionshiro.ini Informations dans le profil , Générer une instance d'usine 
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //Obtenir l'objet utilisateur actuelSubject
        Subject currentUser = SecurityUtils.getSubject();
        // Par l'utilisateur actuel session
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Subject=>session[" + value + "]");
        }
        //Déterminer si l'utilisateur actuel est authentifié
        if (!currentUser.isAuthenticated()) {
            //Token :Token, Je n'ai pas ,Aléatoire
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);  //Mets - toi en place, souviens - toi de moi.
            try {
                currentUser.login(token); // Opération de connexion effectuée 
            } catch (UnknownAccountException uae) {
                //Si   Le nom d'utilisateur n'existe pas
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                //Si   Mot de passe incorrect
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                // L'utilisateur est verrouillé , Si la sortie du mot de passe est excessive , Est verrouillé 
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            //... Capturez plus d'exceptions ici 
            catch (AuthenticationException ae) {
                //Circonstances imprévues ? Erreur ?
            }
        }
        // Imprimer son corps d'identification (Dans ce cas,,Pour le nom d'utilisateur)
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        // Tester si le rôle existe 
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }
        //Granulométrie grossière, La limite est petite 
        // Limites de typage des essais ( Pas au niveau de l'Instance )
        if (currentUser.isPermitted("lightsaber:wield")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }
        //Granulométrie fine, Large gamme de limites 
        // Permissions au niveau de l'Instance (Très puissant.)
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }
        //Déconnecter
        currentUser.logout();
        //Sortie
        System.exit(0);
    }
}

Trois、SpringBoot Intégration Shiro

1. Écrire un environnement de test

1. Créer un nouveau springboot Module

2.Importer SpringBoot Et Shiro Consolider les dépendances des paquets

 <!--SpringBoot Et Shiro Paquet de consolidation-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>

Voici le Profil d'écriture
Shiro Trois éléments

Subject        Utilisateurs      ->    ShiroFilterFactoryBean
SecurityManager        Gérer tous les utilisateurs  -> DefaultWebSecurityManager
Realm          Données de connexion
L'ordre dans lequel les objets sont créés en action réelle : realm -> securityManager -> subject

3. Écrire personnalisé realm ,Héritage requis AuthorizingRealm

//Personnalisé UserRealm        extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
    //Autorisation
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // Imprimer un indice 
        System.out.println("Méthode d'autorisation mise en oeuvre");
        return null;
    }

    //Certification
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // Imprimer un indice 
        System.out.println("Méthode de certification appliquée");
        return null;
    }
}

4.Créer un nouveauShiroConfigProfil

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean:3
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebsecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //Configuration du gestionnaire de sécurité
        bean.setSecurityManager(defaultWebsecurityManager);
        return bean;
    }
    //DefaultWebSecurityManager:2
    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        //FermerUserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }
    //Créationrealm Objet,Classe personnalisée requise:1
    @Bean(name="userRealm")
    public UserRealm userRealm(){
        return new UserRealm();
    }
}

5.Test réussi!

2.Utiliser

1. Interception de connexion

IngetShiroFilterFactoryBean Ajouter une demande de connexion à intercepter à la méthode

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean:3
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebsecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //Configuration du gestionnaire de sécurité
        bean.setSecurityManager(defaultWebsecurityManager);
        //AjoutershiroFiltre intégré pour
        /*
            anon :  Pas besoin de certification ,Est accessible
            authc : Doit être authentifié pour accéder
            user : Doit avoir “Souviens - toi de moi.” Fonction seulement
            perms : Avoir accès à une ressource
            role : Avoir une autorisation de rôle pour accéder à
         */

        filterMap.put("/user/add","authc");
        filterMap.put("/user/update","authc");
        //Interception
        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put("/user/*","authc");
        bean.setFilterChainDefinitionMap(filterMap);

//        //Définir la demande de connexion
//        bean.setLoginUrl("/toLogin");
        return bean;
    }

Tests:Cliquez sur addLiens, Ne sautez pas à add Page, Au lieu de cela, passez à la page d'atterrissage ,Interception réussie

 2.Authentification de l'utilisateur

1.InController Couche pour écrire une méthode de connexion

    //Méthode de connexion
    @RequestMapping("/login")
    public String login(String username, String password, Model model) {
        //Obtenir l'utilisateur actuel
        Subject subject = SecurityUtils.getSubject();
        //Encapsule les données de connexion de l'utilisateur, Obtenir un jeton 
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //Connexion Et Gestion des exceptions
        try {
            // Méthode d'exécution de la connexion utilisateur ,S'il n'y a pas d'exceptionOKC'est
            subject.login(token);
            return "index";
        } catch (UnknownAccountException e) {
            //Si le nom d'utilisateur n'existe pas
            System.out.println("Le nom d'utilisateur n'existe pas");
            model.addAttribute("msg", "Erreur de nom d'utilisateur");
            return "login";
        } catch (IncorrectCredentialsException ice) {
            // Si le mot de passe est incorrect 
            System.out.println("Mauvais mot de passe");
            model.addAttribute("msg", "Mauvais mot de passe");
            return "login";
        }
    }
}

2.Tests

Vous pouvez voir que la personnalisation a été effectuée en premier UserRealmDansAuthenticationInfoMéthodes, Effectuer à nouveau les opérations liées à la connexion

3.ModifierUserRealmDansdoGetAuthenticationInfoMéthodes

    //Certification
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // Imprimer un indice 
        System.out.println("Méthode de certification appliquée");
        // Nom d'utilisateur Mot de passe
        String name = "root";
        String password = "123456";
        // Obtient le paramètre généré dans le Contrôleur connecté  Token
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // Authentification du nom d'utilisateur 
        if (!token.getUsername().equals(name)){
            // return null UnKnownAccountException
            return null;
        }
        //Authentification par mot de passe, Shiro Faites - le vous - même., Pour éviter tout contact avec le mot de passe 
        //Dernier retour AuthenticationInfo Classe d'implémentation de l'interface,Choisissez ici SimpleAuthenticationInfo
        // Trois paramètres: Obtenir l'authentification de l'utilisateur actuel  ; Mot de passe ; Nom certifié
        return new SimpleAuthenticationInfo("", password, "");
    }
}

4.Tests, Saisissez le mauvais mot de passe

  Saisissez le mot de passe correct ,Vous pouvez vous connecter avec succès

Quatre、ShiroIntégrationMybatis

1.Importer des dépendances

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>
       <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

2.Nouveauapplication.yml

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot Par défaut, ces valeurs de propriété ne sont pas injectées,Besoin de se lier
    #druid Configuration propriétaire de la source de données
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #Configurer l'interception des statistiques de surveillancefilters,stat:Statistiques de surveillance、log4j:Logging、wall:DéfensesqlInjection
    #Si vous permettez de signaler une erreur  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #Importer log4j La dépendance suffit,Maven Adresse:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
  type-aliases-package: com.huang.pojo
  mapper-locations: classpath:mybatis/mapper/*.xml

3.Inapplication.properties

mybatis.type-aliases-package=com.longdi.pojo
mybatis.mapper-locations=classpath:mapper/*.xml

4.Importer des dépendances

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

5.CompilationUserCatégorie

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
        private int id;
        private String name;
        private String pwd;
        private String perms;
}

6.CompilationUserMapper

@Repository
@Mapper
public interface UserMapper {
    public User  queryUserByName(String name);

}

7.CompilationUserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.longdi.mapper.UserMapper">

    <select id="queryUserByName" resultType="User" parameterType="String">
        select * from mybatis.user where name=#{name}
    </select>

</mapper>

8.ServiceCouche

UserServiceInterface:

public interface UserService {
    public User queryUserByName(String name);
}

9.Écrire une classe d'implémentation d'interfaceUserServiceImpl

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    UserMapper userMapper;

    @Override
    public User queryUserByName(String name) {
        return userMapper.queryUserByName(name);
    }
}

10.InShiroSpringbootApplicationTestsTests

@SpringBootTest
class ShiroSpringbootApplicationTests {
    @Autowired
    UserServiceImpl userService;
    @Test
    void contextLoads() {
        System.out.println(userService.queryUserByName("longdi"));
    }
}

11.Connexion réussie à la base de données

Cinq、 Demande d'autorisation de mise en oeuvre

1.InShiroConfig Modifier dans la classe

 2.controllerSaut

 3. Autorisation d'interception de connexion ,Test réussi

 

 4. Autorisation de rédaction doGetAuthorizationInfoMéthodes

 5. Test d'autorisation demandé réussi

Six、ShiroIntégrationThymeleaf

1.Importer des dépendances

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

2.IntégrationShiroDialect

 3.index.html

4.Tests

 5. Dans la certification session

6.Modifierindex.html

版权声明
本文为[LongDi - IDEA]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/10/20211013211842734r.html

Scroll to Top