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.
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
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 :
Enfin, les pages de niveau avec différents niveaux peuvent être sautées selon différentes autorisations.
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
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>
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>
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()); } }
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!