Version: Next

HttpBasic与FormLogin登录认证方式

新建/config/SecurityConfig类

重写protected void configure(HttpSecurity http)


HttpBasic

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic() // 开启httpbasic模式
.and() // 开始配置
.authorizeRequests() // 针对所有请求
.anyRequest()
.authenticated(); // 要求必须先登录
}
}

运行启动,控制台会看到一串SpringSecurity生成的默认密码

Using generated security password: dafeb2e4-630a-4f38-b3c2-6ec89ba71bce

默认用户名user

可以在application.yaml中自己配置用户名密码

spring:
security:
user:
name: admin
password: admin

原理

  • 首先,HttpBasic模式要求传输的用户名密码使用Base64模式进行加密。如果用户名是 "admin" ,密码是“ admin”,则将字符串"admin:admin"使用Base64编码算法加密。加密结果可能是:YWtaW46YWRtaW4=。
  • 然后,在Http请求中使用Authorization作为一个Header,“Basic YWtaW46YWRtaW4=“作为Header的值,发送给服务端。(注意这里使用Basic+空格+加密串)
  • 服务器在收到这样的请求时,到达BasicAuthenticationFilter过滤器,将提取“ Authorization”的Header值,并使用用于验证用户身份的相同算法Base64进行解码。
  • 解码结果与登录验证的用户名密码匹配,匹配成功则可以继续过滤器后续的访问。

所以,HttpBasic模式真的是非常简单又简陋的验证模式,Base64的加密算法是可逆的


FormLogin

三要素

  • 登录认证逻辑(静态)
  • 资源访问控制(动态)
  • 用户角色权限(动态)
  • 设置formLogin模式
  • 设置登录页,账号密码输入框属性名,登录后跳转路径
  • 设置各个资源路径的访问权限信息
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //禁用跨站csrf攻击防御,后面的章节会专门讲解
.formLogin()
.loginPage("/login.html")//用户未登录时,访问任何资源都转跳到该路径,即登录页面
.loginProcessingUrl("/login")//登录表单form中action的地址,也就是处理认证请求的路径
.usernameParameter("username")///登录表单form中用户名输入框input的name名,不修改的话默认是username
.passwordParameter("password")//form中密码输入框input的name名,不修改的话默认是password
.defaultSuccessUrl("/index")//登录认证成功后默认转跳的路径
.and()
.authorizeRequests()
.antMatchers("/login.html", "/login").permitAll()//不需要通过登录验证就可以被访问的资源路径
.antMatchers("/biz1", "/biz2") //需要对外暴露的资源路径
.hasAnyAuthority("ROLE_user", "ROLE_admin") //user角色和admin角色都可以访问
.antMatchers("/syslog", "/sysuser")
.hasAnyRole("admin") //admin角色可以访问
//.antMatchers("/syslog").hasAuthority("sys:log")
//.antMatchers("/sysuser").hasAuthority("sys:user")
.anyRequest().authenticated();
}
}

为用户设置权限、角色

  • 重写protected void configure(AuthenticaitonManagerBuilder auth)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("123456"))
.roles("user")
.and()
.withUser("admin")
.password(passwordEncoder().encode("123456"))
//.authorities("sys:log","sys:user")
.roles("admin")
.and()
.passwordEncoder(passwordEncoder());//配置BCrypt加密
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
  • inMemoryAuthentication指的是在内存里面存储用户的身份认证和授权信息。
  • withUser("user")用户名是user
  • password(passwordEncoder().encode("123456"))密码是加密之后的123456
  • authorities("sys:log","sys:user")指的是admin用户拥有资源ID对应的资源访问的的权限:"/syslog"和"/sysuser"
  • roles()方法用于指定用户的角色,一个用户可以有多个角色
  • antMatchers("/sysuser").hasAuthority("sys:user")配合.authorities("sys:log","sys:user")
  • .antMatchers("/syslog", "/sysuser").hasAnyRole("admin")配合.roles("admin")

静态资源处理

对于静态资源,不需要设置权限

  • 重写configure(WebSecuriy web)方法
@Override
public void configure(WebSecurity web) {
//将项目中静态资源路径开放出来
web.ignoring().antMatchers( "/css/**", "/fonts/**", "/img/**", "/js/**");
}

测试

修改login.html中的表单提交地址

<form action="/login" method="post">
<span>用户名:<input type="text" name="username"/></span>
<span>密码:<input type="password" name="password"/></span>
<input type="submit" value="登录">
</form>