Maison  >  Article  >  Java  >  Comment utiliser SpringBoot+SpringSecurity pour implémenter l'authentification d'autorisation basée sur des données réelles

Comment utiliser SpringBoot+SpringSecurity pour implémenter l'authentification d'autorisation basée sur des données réelles

王林
王林avant
2023-05-13 19:34:20940parcourir

(1) Présentation

Spring Security est un cadre d'authentification et de contrôle d'accès puissant et hautement personnalisable qui fait principalement deux choses : l'authentification et l'autorisation. J'ai déjà écrit un blog sur Spring Security, mais à cette époque, je n'avais présenté qu'un cas basé sur des données fictives. Dans ce numéro, je présenterai la mise en œuvre de l'authentification et de l'autorisation basées sur des données réelles.

(2) Construction préliminaire du projet

Afin de mieux démontrer SpringSecurity, nous construisons d'abord un projet Web simple. Introduire la dépendance thymeleaf

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-thymeleaf</artifactid>
</dependency>
<dependency>
    <groupid>org.thymeleaf</groupid>
    <artifactid>thymeleaf-spring5</artifactid>
</dependency>
<dependency>
    <groupid>org.thymeleaf.extras</groupid>
    <artifactid>thymeleaf-extras-java8time</artifactid>
</dependency>

Créer une page de connexion, une page d'accueil, puis plusieurs pages d'affichage de différents niveaux : login.html

nbsp;html>


    <meta>
    <title>登陆页</title>


<div>
    <form>
        <h3>登陆页</h3>
        <input>
        <input>
        <button>登陆</button>
    </form>
</div>

index.html

nbsp;html>


    <meta>
    <title>首页</title>


<div>
    <h3>首页</h3>
    <a>登陆</a>
    <div>
        <div>
            <h4>level1</h4>
            <a>level-1-1</a>
            <hr>
            <a>level-1-2</a>
        </div>
        <div>
            <h4>level2</h4>
            <a>level-2-1</a>
            <hr>
            <a>level-2-2</a>
        </div>
        <div>
            <h4>level3</h4>
            <a>level-3-1</a>
            <hr>
            <a>level-3-2</a>
        </div>
    </div>
</div>

De plus, il y a plusieurs pages de différents niveaux

Comment utiliser SpringBoot+SpringSecurity pour implémenter lauthentification dautorisation basée sur des données réelles

respectivement Écrivez votre numéro correspondant dans le corps.

nbsp;html>


    <meta>
    <title>Title</title>


level-1-1

Enfin, écrivez un contrôleur pour recevoir la demande :

@Controller
public class RouteController {

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

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

    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id")String id){
        return "level1/"+id;
    }
    @RequestMapping("/level2/{id}")
    public String level2(@PathVariable("id")String id){
        return "level2/"+id;
    }
    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id")String id){
        return "level3/"+id;
    }
}

L'effet final est le suivant :

Comment utiliser SpringBoot+SpringSecurity pour implémenter lauthentification dautorisation basée sur des données réelles

Enfin, les pages de niveau avec différents niveaux peuvent être sautées selon différentes autorisations.

Comment utiliser SpringBoot+SpringSecurity pour implémenter lauthentification dautorisation basée sur des données réelles

L'arrière-plan est implémenté sur la base de données Mybatis et Mysql, donc en plus d'introduire les dépendances SpringSecurity, nous devons également introduire les dépendances liées à Mybatis :

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-security</artifactid>
</dependency>
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-jdbc</artifactid>
</dependency>
<dependency>
    <groupid>mysql</groupid>
    <artifactid>mysql-connector-java</artifactid>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupid>org.mybatis.spring.boot</groupid>
    <artifactid>mybatis-spring-boot-starter</artifactid>
    <version>2.1.3</version>
</dependency>

Ajouter des informations relatives à la source de données dans le fichier de configuration, ainsi que Mybatis configuration :

spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.mapper-locations=classpath:mapper/*.xml

(3) Implémentation de l'authentification et de l'autorisation

3.1 Conception de la structure de la table

L'authentification et l'autorisation doivent être divisées en deux tables dans la conception de la table. Une table stocke les informations utilisateur, y compris les mots de passe, etc., et l'autre table stocke. Les informations d'autorisation sont également requises. Un tableau établit l'association entre les utilisateurs et les autorisations, donnant la structure du tableau final :

CREATE TABLE `roles` (
  `id` int(4) NOT NULL,
  `rolename` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `sysuser` (
  `id` int(4) NOT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `user_role` (
  `id` int(4) NOT NULL,
  `user_id` int(4) DEFAULT NULL,
  `role_id` int(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

L'étape suivante concerne les classes d'entités, les interfaces Mapper et les fichiers XML pour ces trois tableaux. regardez le code, principalement pour implémenter un passe utilisateur Opérations pour rechercher les utilisateurs et les autorisations associées par nom :

@Data
public class Roles {
    private Integer id;
    private String roleName;
}

@Data
public class SysUser {
    private Integer id;
    private String userName;
    private String password;
    private List<roles> roles;
}</roles>

Interface Mapper :

public interface UserMapper {
    public SysUser getUserByUserName(@Param("userName") String userName);
}

implémentation xml :

<?xml  version="1.0" encoding="UTF-8" ?>
nbsp;mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper>
    <resultmap>
        <id></id>
        <result></result>
        <result></result>
        <collection>
            <result></result>
        </collection>
    </resultmap>
    <select>
        select sysuser.*,roles.rolename
        from sysuser
        LEFT JOIN user_role on sysuser.id= user_role.user_id
        LEFT JOIN roles on user_role.role_id=roles.id
        where username= #{userName}
    </select>
</mapper>

3.2 Processus d'authentification

Le processus d'authentification de SpringSecurity est comme ça, trouvez d'abord dans la base de données via le nom d'utilisateur ou un autre identifiant unique. Pour cet utilisateur, le mot de passe de l'utilisateur est stocké dans un cryptage asymétrique. Après avoir obtenu l'utilisateur, le mot de passe transmis par la réception est crypté et comparé aux champs cryptés de la base de données pour réussir l'authentification.

La première étape du processus ci-dessus, pour rechercher l'utilisateur par nom d'utilisateur, doit être implémentée via le service Service, et ce service Service doit hériter de l'interface UserDetailsService dans Spring Security. Cette interface renvoie un objet SpringSecurity User.

@Service
public class UserService implements UserDetailsService {

    @Resource
    private UserMapper userMapper;
    //根据用户名找到对应的用户信息
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        SysUser sysUser = userMapper.getUserByUserName(s);
        if (sysUser!=null){
            List<grantedauthority> roles=new ArrayList();
            sysUser.getRoles().stream().forEach(x->{
                roles.add(new SimpleGrantedAuthority(x.getRoleName()));
            });
            return new User(sysUser.getUserName(),sysUser.getPassword(),roles);
        }
        throw new UsernameNotFoundException("用户未找到");
    }
}</grantedauthority>

3.3 Configuration de l'interception de sécurité

Après avoir terminé les étapes ci-dessus, commencez à configurer la sécurité. Écrivez une méthode de configuration SecurityConfig Le niveau de code est très simple. Lorsque l'authentification est transmise à l'objet userService, le mot de passe est retiré de la base de données et. le frontal sera automatiquement transmis au mot de passe pour comparaison. Dans le même temps, la collection de rôles est également transmise dans userService et différentes autorisations peuvent être attachées à différentes pages au point d'autorisation.

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;
    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页所有人都能访问,level页面只有有权限的人才能访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
        //没有权限默认跳到登陆页,默认会重定向到/login
        http.formLogin();
    }

    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());

    }
}

3.4 Autres points à noter

La méthode de cryptage des mots de passe que j'ai utilisée lors de l'authentification est BCryptPasswordEncoder, donc les mots de passe stockés dans la base de données doivent également être cryptés. La méthode courante consiste à crypter et à stocker les mots de passe de la même manière lors de l'inscription. . Entrez dans la base de données :

String password="xxx";
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode=bCryptPasswordEncoder.encode(password);

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer