Spring框架Security(认证)快速上手

在处理Spring安全框架时,通常可以选择Shiro或者Security,做认证授权加密等。
推荐非SpringBoot,使用Shiro,SpringBoot项目使用Security
学习网址:
Security
Shiro

目录

    • 1.SpringBoot快速装配Security
      • 引入依赖
      • 实现UserDetailsService
      • 选择加密器
    • 2.认证结合数据库使用
      • 步骤
        • 编写数据库
        • 整合Mybatis
        • 编写Entity实体类以及Dao类
        • 修改UserDetailsService
    • 3.给公共URL放行
      • 开启Spring Security Web安全配置
      • 编辑资源拦截配置与开放URL权限
    • 4.自定义登录界面
    • 5. Remember me

1.SpringBoot快速装配Security

基础步骤:

引入依赖

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

重启SpringBoot项目,访问网页,这里使用后台提供的账号密码登录
Spring框架Security(认证)快速上手_第1张图片

实现UserDetailsService

这里开始账号,密码,角色认证(对应User中参数)

@Service
public class DetailService implements UserDetailsService {

    @Autowired
    private PasswordEncoder pe;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return new User("xiaoming",pe.encode("666"),new ArrayList<>());
    }
}

选择加密器

这里使用PasswordEncoder做密码加密

  • 把加密器交给Spring管理 (设置配置文件@Bean)

这里使用加密算法BCryptPasswordEncoder
其他加密算法:
BCryptPasswordEncoder
Argon2PasswordEncoder
Pbkdf2PasswordEncoder
SCryptPasswordEncoder(单向加密)
加密器详细


@Configuration
public class SecurityConfig {

    @Bean
    public PasswordEncoder getPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

密码必须加密,否则提示Encoded password does not look like BCrypt

2.认证结合数据库使用

步骤

编写数据库

必须包含账号密码角色

整合Mybatis

编写Entity实体类以及Dao类

注意:由于UserDetailsService返回类型为UserDetails,因此创建的实体类需要实现UserDetails接口

实现UserDetails类重写以下方法。

	private Integer id;
    private String username;
    private String password;
    private String realName;
    private Boolean enabled;
    private Boolean locked;
    private Boolean expired;
    private Boolean credentialsExpired;
    private Date createTime;
    private Date loginTime;
//账号是否过期,0-已过期,1-未过期
    @Override
    public boolean isAccountNonExpired() {
        return this.expired;
    }
    //账号是否被锁定,0-锁定,1-未锁定
    @Override
    public boolean isAccountNonLocked() {
        return this.locked;
    }
    //账号凭证是否过期,0-已过期,1-未过期
    @Override
    public boolean isCredentialsNonExpired() {
        return this.credentialsExpired;
    }
    //账号是否有效,0-失效,1-有效
    @Override
    public boolean isEnabled() {
        return this.enabled;
    }
    //Collection  authorities,这个属性中存储了这个用户所有的权限
    //暂未使用,后面授权补充
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

重写的方法可以用做封号处理等

修改UserDetailsService

直接找数据库要信息就可以了


@Service
public class DetailService implements UserDetailsService {

    @Autowired
    private PasswordEncoder pe;

    @Autowired
    private SysUserDao sysUserDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserDao.selectByUsername(username);
        return sysUser;
    }
}

注意数据库中密码也必须是PasswordEncoder (使用同样的加密方式)加密过的

前面Security默认将所有URL拦截掉,需要登录认证才能访问URL下面我们把将公开的URL开放供所有人访问

3.给公共URL放行

开启Spring Security Web安全配置

  • 在SecurityConfig中添加注解@EnableWebSecurity
  • SecurityConfig类继承WebSecurityConfigurerAdapter
  1. 控制Spring Security是否使用调试模式(通过注解属性debug指定),缺省为false,表示缺省不使用调试模式;
  2. 导入 WebSecurityConfiguration,用于配置Web安全过滤器FilterChainProxy;
  3. 如果是Servlet 环境,导入WebMvcSecurityConfiguration;
  4. 如果是OAuth2环境,导入OAuth2ClientConfiguration;
  5. 使用注解@EnableGlobalAuthentication启用全局认证机制;

编辑资源拦截配置与开放URL权限

Spring框架Security(认证)快速上手_第2张图片

重写

configure(HttpSecurity http)

先观察原本的configure(HttpSecurity http) 方法如下。
Spring框架Security(认证)快速上手_第3张图片
重写放权

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/hello").permitAll()//所有人可以访问
                .anyRequest().authenticated();//配置所有路径只有登录才可以访问

        http.formLogin();//开启表单登录
        http.httpBasic();
    }

到这里已经成功放行了
下面简单记录一下几种主要配置

URL匹配常用的几种方式

  1. requestMatchers() 配置一个request Mather数组,参数为RequestMatcher 对象,其match 规则自定义,需要的时候放在最前面,对需要匹配的的规则进行自定义与过滤
  2. antMatchers() 配置一个request Mather 的 string数组,参数为 ant 路径格式, 直接匹配url
  3. anyRequest 匹配任意url,无参,必须放在最后面

URL权限
permitAll() 已登录和未登录用户都能访问
authenticated() 已登录用户能访问,未登录用户不能访问
anonymous() 未登录用户能访问,已登录用户不能访问
denyAll() 已登录和未登录用户都不能访问
rememberMe() 通过“记住我”功能直接登录的用户可以访问
fullyAuthenticated() 不是通过“记住我”功能直接登录的用户可以访问

登录login配置
1.formLogin() 配置基于表单登录的认证方式
loginPage() 登录页地址,默认“/login”
loginProcessingUrl 提交表单之后真正处理登录请求的地址
defaultSuccessUrl 默认跳转到 Referer 来源页面,如果 Referer 为空,没有来源页,则跳转到默认设置的页面
successForwardUrl 登录后一律跳转到指定的地址
failuerUrl登录失败之后系统转向的url,默认是loginPage + “?error”
failuerHandler登录失败之后的处理器
successHandler登录成功之后的处理器
2.httpBasic() 配置Http Basic认证方式
了解httpBasic

登出logout配置
logout() 配置登出
logoutUrl 登出url,默认是/logout
logoutSuccessUrl 登出成功后跳转的 url 默认是"/login?logout"
logoutSuccessHandler 登出成功处理器,设置后会把logoutSuccessUrl 置为null

4.自定义登录界面

  • 添加自己的登录界面
    注意两个地方
    Spring框架Security(认证)快速上手_第4张图片
  • 放开权限
  • 按照上面登录login配置来配置跳转跟传参地址
    Spring框架Security(认证)快速上手_第5张图片
  • 关闭csrf或者在登录表单增加csrf字段
    注意:

如果这里运行访问http://localhost:8080/myLogin.html后台不报错,但是网页报
*This application has no explicit mapping for /error, so you are seeing this as a fallback. Mon May 09 17:03:35 CST 2022 There was an unexpected error (type=Not Found, status=404). No message available*
不必惊慌,有可能原因是:

  1. 你的Application运行类位置放错了,所有包的外面就可以了
    Spring框架Security(认证)快速上手_第6张图片
  2. 可能是你的Maven没有配置或者出现了问题,重新修改个Maven配置就可以了。

5. Remember me

这个功能主要是做网页登录记住我选项达到未来一段时间不用登录的效果。
以下代码都添加在SecurityConfig配置类中。

  1. Spring Security提供了一个JdbcTokenRepositoryImpl类来帮助简化Remember Me功能的开发,创建这个类并放到Spring容器中,JdbcTokenRepositoryImpl需要数据源,通过注入的方式提供。
@Autowired
private DataSource dataSource;  //数据库连接池

@Bean
public PersistentTokenRepository persistentTokenRepositoryBean(){
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
    //指定数据源
    jdbcTokenRepository.setDataSource(dataSource);
    //启动时创建表,第一次启动时使用,后面要注释掉
    jdbcTokenRepository.setCreateTableOnStartup(true);
    return jdbcTokenRepository;
}

如果我们运行第二次 而jdbcTokenRepository.setCreateTableOnStartup(true);没有注释那么后台报
Error creating bean with name ‘springSecurityFilterChain’ defined in class path resource …nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table ‘persistent_logins’ already exists,意思是这个存放记住我的相关表已经创建过了。

  1. 使用Remember-Me自动登录时,也需要查询用户的信息,需要指定UserDetailsService。
@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService); 
}
  1. 配置token的持久化方式及有效时长
http.rememberMe().tokenRepository(persistentTokenRepositoryBean()).tokenValiditySeconds(10*24*60*60);
  1. 登录页面增加remember-me字段

Spring框架Security(认证)快速上手_第7张图片

到这里Spring Security认证部分已经基本上是完了。

提一句一般用JWT替换httpBasic,只需要Spring Security整合JWT就可以了。

你可能感兴趣的:(spring,java,spring,boot)