Springboot基于SpringSecurity简单的登录验证


1.1导入依赖

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

1.2配置用户信息和权限类

SpringSecurity中存在一个UserDetails接口的实现类org.springframework.security.core.userdetails.User,它有三个参数,分别是用户名、密码和权限集。我们需要通过自定义 UserDetailsService将用户和权限信息注入进去。(也可以直接创建写入,通过自定义UserDetailsService主要是为了从数据库中读取用户信息)。

  • 直接配置
       @Bean
    public UserDetailsService userDetailsService() throws Exception {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
        return manager;
    }
  • 从数据库中读取
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private SysUserService userService;

    @Autowired
    private SysRoleService roleService;

    @Autowired
    private SysUserRoleService userRoleService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        // 从数据库中取出用户信息
        SysUser user = userService.selectByName(username);

        // 判断用户是否存在
        if(user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }

        // 添加权限
        List<SysUserRole> userRoles = userRoleService.listByUserId(user.getId());
        for (SysUserRole userRole : userRoles) {
            SysRole role = roleService.selectById(userRole.getRoleId());
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }

        // 返回UserDetails实现类
        return new User(user.getName(), user.getPassword(), authorities);
    }
}

1.3自定义WebSecurityConfigurerAdapter的子类进行自定义登录认证配置

Spring Security基于表单的身份验证是WebSecurityConfigurerAdapter在configure(HttpSecurity http)方法中提供了一个默认配置,我们可通过自定义其子类WebSecurityConfig,实现自己的表单验证登录配置。
默认配置

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated() 1
            .and()
        .formLogin() 2
            .and()
        .httpBasic(); 3
}
  1. 确保对我们的应用程序的任何请求都要求用户进行身份验证
  2. 允许用户使用基于表单的登录进行身份验证
  3. 允许用户使用HTTP基本身份验证进行身份验证

虽然自动生成的登录页面便于快速启动和运行,但大多数应用程序都希望提供自己的登录页面。为此,我们可以更新我们的配置,如下所示:

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login") 1
            .permitAll();        2
}
  1. 更新的配置指定登录页面的位置。
  2. 我们必须授予所有用户(即未经身份验证的用户)访问我们的登录页面的权限。formLogin().permitAll()方法允许为与基于表单的登录相关联的所有URL授予对所有用户的访问权限。
    我们可以通过向http.authorizeRequests()方法添加多个子项来指定网址的自定义要求。例如:
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()                                                                1
            .antMatchers("/resources/**", "/signup", "/about").permitAll()                  2
            .antMatchers("/admin/**").hasRole("ADMIN")                                      3
            .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")            4
            .anyRequest().authenticated()                                                   5
            .and()
        // ...
        .formLogin();
}
  1. http.authorizeRequests()方法有多个子项,每个匹配器按其声明的顺序进行考虑。
  2. 我们指定了任何用户都可以访问的多种URL模式。具体来说,如果URL以“/ resources /”开头,等于“/ signup”或等于“/ about”,则任何用户都可以访问请求。
  3. 任何以“/ admin /”开头的URL都将仅限于具有“ROLE_ADMIN”角色的用户。您会注意到,由于我们正在调用hasRole方法,因此我们不需要指定“ROLE_”前缀。
  4. 任何以“/ db /”开头的URL都要求用户同时拥有“ROLE_ADMIN”和“ROLE_DBA”。您会注意到,由于我们使用的是hasRole表达式,因此我们不需要指定“ROLE_”前缀。
  5. 任何尚未匹配的URL只需要对用户进行身份验证

使用WebSecurityConfigurerAdapter时,会自动应用注销功能。默认情况下,访问URL /logout将通过以下方式记录用户:

  • 使HTTP会话无效
  • 清理已配置的任何RememberMe身份验证
  • 清除SecurityContextHolder
  • 重定向到/login?logout

但是,与配置登录功能类似,您还可以使用各种选项来进一步自定义注销要求:

protected void configure(HttpSecurity http) throws Exception {
    http
        .logout()                                                                1
            .logoutUrl("/my/logout")                                                 2
            .logoutSuccessUrl("/my/index")                                           3
            .logoutSuccessHandler(logoutSuccessHandler)                              4
            .invalidateHttpSession(true)                                             5
            .addLogoutHandler(logoutHandler)                                         6
            .deleteCookies(cookieNamesToClear)                                       7
            .and()
        ...
}
  1. 提供注销支持。使用WebSecurityConfigurerAdapter时会自动应用此选项。
  2. 触发注销的URL(默认为/logout)。如果启用了CSRF保护(默认),则该请求也必须是POST。
  3. 注销后重定向到的URL。默认值为/login?logout。
  4. 我们指定一个自定义LogoutSuccessHandler。如果指定了此项,则忽略logoutSuccessUrl()。
  5. 指定在注销时是否使HttpSession无效。默认情况下这是真的。
  6. 添加LogoutHandler。默认情况下,SecurityContextLogoutHandler被添加为最后一个LogoutHandler。
  7. 允许指定在注销成功时删除的cookie的名称。这是显式添加CookieClearingLogoutHandler的快捷方式。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM