SpringBoot integrado SpringSecurity tutorial completo

Desenvolva um hábito, goste primeiro e depois observe !!!

1. Introdução

O projeto anterior usava a estrutura SSM, então a estrutura de segurança que escolhemos foi shiro, mas como o diretor técnico integrou os módulos que criamos em um formulário de microsserviço, usamos springboot para migrar novamente nosso projeto. .

Altere-o mais tarde, migre a maior parte da lógica e, em seguida, adicione a estrutura de segurança, porque estamos usando o springboot agora, então escolhemos usar o springsecurity como uma estrutura de segurança, embora o springboot possa funcionar perfeitamente com o springsecurity, mas até Assim, demorou um dia para que todo o framework de segurança fosse incorporado. O motivo é que o próprio up é muito culinário.
Insira a descrição da imagem aqui
Não há muito o que dizer, aqui está o tutorial completo, espero que ajude você.

2. Processo

Na verdade, todo o processo é relativamente simples, afinal, é tudo da família da mola, então a adaptação é de fato relativamente simples.

Na verdade, é principalmente dividido em três partes, essas três partes são UserDetails UserDetailsService 和SecurityConfig

  • UserDetails
    porque todos nós precisamos ler as informações finais da conta do banco de dados interno, então precisamos implementar algum método na classe de entidade UserDetails da interface do usuário que definimos, que inclui principalmente funções de usuário e informações de permissões nessa seção.
  • UserDetailsService
    Na verdade, vemos Service saberá o que significa é que precisamos alcançar o nosso método UserDetailsService no UserService correspondente, o principal é conseguir a autenticação do usuário e operações de autorização
  • SecurityConfig
    isto para ver o nome a saber é o arquivo de configuração. Aqui a senha de criptografia de configuração principal , filtragem de HTTP e outras funções

A seguir está o tutorial detalhado

2.1 Importar dependências

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.2 Classe de entidade do usuário implementa UserDetails

Aqui, clicamos e observamos e descobrimos que UserDetails contém principalmente os seguintes atributos:
Insira a descrição da imagem aqui

Aqui, discutimos principalmente o significado desses atributos

  • Coleção <? Extends GrantedAuthority> getAuthorities (); // Usuário权限集
  • String getPassword (); // Usuário criptografado密码
  • String getUsername (); // No aplicativo唯一的用户名
  • boolean isAccountNonExpired (); // A conta expirou
  • boolean isAccountNonLocked (); // A conta está bloqueada
  • boolean isCredentialsNonExpired (); // Se o certificado expirou
  • boolean isEnabled (); // O usuário está disponível

Quando herdamos a interface UserDetails, precisamos reescrever todos os métodos acima, com o seguinte código:

 private Collection<? extends GrantedAuthority> authorities;//这里说是权限集,其实里面存放的其实是用户的角色信息,并且是字符串的形式
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    
    
    return this.authorities;//这里的返回类型是固定的,不能修改成你自己定义的角色对象
}

@Override
public String getUsername() {
    
    
    return loginName;//这里返回你自己定义的唯一用户名的白能量名称
}
//下面四个默认都返回true就行了
@Override
public boolean isAccountNonExpired() {
    
    
    return true;
}

@Override
public boolean isAccountNonLocked() {
    
    
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    
    
    return true;
}

@Override
public boolean isEnabled() {
    
    
    return true;
}

2.3 A camada de negócios do usuário implementa UserDetailsService

Aqui, precisamos herdar nosso UserService de UserDetailsService e, em seguida, implementar os métodos nele. Aqui, clicamos no código-fonte e descobrimos que existe um método nele.
Insira a descrição da imagem aqui
Aqui, reescrevemos seu método.

@SneakyThrows
@Override
public UserDao loadUserByUsername(String username) throws AuthenticationException {
    
    
    //首先通过用户名查询是否有该用户
    UserDao userDao=userDaoMapper.getUserByLoginName(username);
    //System.out.println(userDao);
    //如果用户存在就开始执行身份认证以及授权的相关操作
    if(userDao!=null)
    {
    
    
//            HttpSession session = request.getSession();
//            session.setAttribute("userDao",userDao);
//            session.setAttribute("sessusername",username);
        //这里是判断用户的状态即是否锁定
        if(userDao.getState()==0)
        {
    
    
            throw new AccountLockedException("账户已锁定!");
        }
        else {
    
    
            List<GrantedAuthority> authorities = new ArrayList<>();
            //查询出来该用户的角色列表
            List<RoleDao> roleDaoList=roleService.getRoleByUserId(userDao.getUserId());
            //权限列表
            List<RightDao> rightDaoList=new ArrayList<>();
            for(RoleDao roleDao:roleDaoList)
            {
    
    
                authorities.add(new SimpleGrantedAuthority("ROLE_"+roleDao.getName()));
                for(RightDao rightDao:rightService.getRightsByRoleId(roleDao.getRoleId()))
                {
    
    
                    rightDaoList.add(rightDao);
                }
            }
//            System.out.println(username+"用户已经登录");
//            System.out.println("有以下角色");
//            for(GrantedAuthority a:authorities)
//                System.out.println(a);
//            System.out.println("有以下权限");
//            for(RightDao rightDao:rightDaoList)
//                System.out.println(rightDao);
            return new UserDao(username,userDao.getPassword(),authorities,rightDaoList);
        }

    }
    else
    {
    
    
        throw new UsernameNotFoundException("用户名不存在!");
    }
}

Existem alguns pontos a serem observados aqui

1. Para as funções do usuário, springsecurity todas as informações são armazenadas authoritiesnesta lista, e quando fomos ver os tipos de dados do ponto dentro da loja, quando podemos encontrar GrantedAuthorityna natureza é de fato uma string,
Insira a descrição da imagem aqui
então adicionamos em nossa visão à authoritieslista de SimpleGrantedAuthoritycomo era
Insira a descrição da imagem aqui
então vemos que ele pode encontrar apenas um construtor, o construtor e a variável é uma string de papel, não o papel de nossa própria definição do objeto, e há um ponto a ser observado é que adicionamos A string de função deve estar neste formato: ROLE_角色名caso contrário, springsecurity não será capaz de identificar as informações da função
3. Há também nosso objeto de retorno final, seu objeto de retorno padrão é UserDetails,
Insira a descrição da imagem aqui
então seu objeto de retorno padrão deve ser assim

return new UserDao(username,userDao.getPassword(),authorities);

Retorne um objeto User que contém o nome de usuário, a senha real do nome de usuário e o conjunto de funções, mas eu adicionei um atributo adicional aqui, o conjunto de permissões, porque posso usar a operação de permissão mais tarde, então irei retorná-lo juntos, este Atributos não são obrigatórios.

Mas se houver propriedades adicionais retornadas, você precisará definir seu construtor correspondente no objeto User, assim como eu:
Insira a descrição da imagem aqui

  1. Preste atenção no formulário de retorno da senha, aqui está a senha real do usuário que é retornado diretamente (aqui ela foi criptografada), caso contrário o link de autenticação não poderá ser realizado.

Esse básico 身份验证以及授权操作foi concluído

2.4 Escrevendo a classe de configuração SecurityConfig do Spring Security

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled=true,jsr250Enabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Autowired
    UserService userService;

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
    
    
        return super.authenticationManagerBean();
    }
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
    
    
        // 设置默认的加密方式
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder builder) throws Exception {
    
    
        builder.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
    /**
     * 静态资源设置
     */
//    @Override
//    public void configure(WebSecurity webSecurity) {
    
    
//        //不拦截静态资源,所有用户均可访问的资源
//        webSecurity.ignoring().antMatchers(
//                "/",
//                "/css/**",
//                "/js/**",
//                "/images/**",
//                "/layui/**"
//        );
//    }

    /**
     * http请求设置
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
    
    
        http

                .authorizeRequests()
                    .antMatchers("/","/login").permitAll()
                    .antMatchers("/admin/**").hasRole("admin")
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .defaultSuccessUrl("/swagger-ui.html")
                    .failureUrl("/login?error")
                    .permitAll()
                    .and()
                .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/login")
                    .permitAll()
                    .and()
                .httpBasic()
                    .disable()
                .csrf()
                    .disable();
    }

}

Aqui, prestamos atenção principalmente aos seguintes pontos:

  • Devemos querer criptografar a regra é injetada no contêiner de primavera, caso contrário, ocorrerá um erro, seguido pela adição da regra de criptografia ao nosso serviço, para autenticação quando for necessário para resolver nossa senha já criptografada, caso contrário, ele não pode ser resolvido , Principalmente este código:
@Bean
public BCryptPasswordEncoder passwordEncoder() {
    
    
   // 设置默认的加密方式
   return new BCryptPasswordEncoder();
}
@Autowired
public void configure(AuthenticationManagerBuilder builder) throws Exception {
    
    
   builder.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
  • Defina nossas condições de filtro.
    Aqui está principalmente em configure (HttpSecurity http) . Vendo que o parâmetro é HTTP, sabemos que é principalmente para filtrar e autenticar solicitações HTTP. Primeiro, vamos olhar o primeiro código:
.authorizeRequests()
    .antMatchers("/","/login").permitAll()
    .antMatchers("/admin/**").hasRole("admin")
    .anyRequest().authenticated()

Aqui definimos a página de login como todas permitidas e, em seguida, definimos que todas as solicitações em / admin precisam de usuários com a função de administrador para poder acessar e, em seguida, todas as solicitações exigem que os usuários estejam logados antes que possam acessar
todos Depois que a definição de uma regra de solicitação for concluída, se quiser redefinir outra regra de solicitação, você pode dividi-la por e e escrever outra regra de solicitação.

Aqui vemos a segunda parte do código:

.formLogin()
    .usernameParameter("username")
    .passwordParameter("password")
    .defaultSuccessUrl("/swagger-ui.html")
    .failureUrl("/login?error")
    .permitAll()

Página de login personalizada e página de erro

O terceiro código:

.logout()
    .logoutUrl("/logout")
    .logoutSuccessUrl("/login")
    .permitAll()

Aqui definimos a operação de logout. Após o logout, as informações do usuário se tornam inválidas e qualquer solicitação precisa ser logada novamente para ser concluída

3. Demonstração de efeito

Vamos primeiro dar uma olhada em algumas das operações do usuário administrador :
Insira a descrição da imagem aqui
podemos ver que quando acessamos o swagger, ele é interceptado diretamente e só pode ser acessado após o login e, por ser um usuário administrador, todas as operações podem ser realizadas. Depois de fazer o logout, quando visitarmos o swagger novamente, podemos descobrir que a solicitação ainda está interceptada, portanto, a função de logout também é implementada.

Nós olhamos para a operação dos visitantes :
Insira a descrição da imagem aqui
Como turistas, depois de fazer o login, essas operações não são permitidas, você pode ver 403 erros são relatados, o que significa que não há acesso.

Não é fácil ser original. Espero que todos possam prestar atenção a uma onda. É bom gostar. Já
vi aqui. Se você acha que é útil para você, pode seguir minha conta pública. Os novatos precisam de sua ajuda !!!

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/lovely__RR/article/details/109229515
Recomendado
Clasificación