同步操作将从 JustryDeng/notebook 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
软硬件环境:
声明: 本文主要示例入门级SpringSecurity,对其理论知识不作深入分析。
提供以下API,以供之后的演示:
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 用于测试的controller层
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2019/11/26 10:05
*/
@Slf4j
@RestController
public class DemoController {
/**
* 未登录就可访问的页面
*
* 注: 用于.permitAll()测试。
*/
@GetMapping("/hello")
public String hello() {
return "hello 靓仔~";
}
/**
* 首页(登录成功后跳转至此页)
*
* 注:默认的,表单登录 登录成功时, 是以POST重定向至登陆成功页的,所以这里至少要支持POST请求。
*/
@RequestMapping(value = "/index", method = {RequestMethod.GET, RequestMethod.POST})
public String home() {
return "欢迎来到index~";
}
/**
* 登录失败页
*/
@GetMapping("/login/failed")
public String error() {
return "登录失败~";
}
/**
* 登出成功页
*/
@GetMapping("/logout/success")
public String logout() {
return "您已成功退出~";
}
/**
* 鉴权失败页
*/
@GetMapping("/403")
public String forbidden() {
return "小伙~你的权限不够~";
}
@GetMapping("/user")
public String user() {
return "普通用户~";
}
@GetMapping("/dba")
public String dba() {
return "数据库DBA~";
}
@GetMapping("/admin")
public String admin() {
return "超级管理员~";
}
}
<!-- spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
提示一: 这里主要以图片的形式进行说明,MyWebSecurityConfigurerAdapter类文字版的完整代码在本文末给出。
提示二: WebSecurityConfigurerAdapter类中,configure(AuthenticationManagerBuilder auth)方法、configure(HttpSecurity http)方法以及configure(WebSecurity web)方法相对常用,下面对这三个方法进行简单说明并重写示例。
第一小步(可选): 重写configure(WebSecurity web)方法。
此方法相关的部分配置说明(未显示父类方法):
(简单)示例:
@Override
public void configure(WebSecurity web) {
/*
* 对于那些没必要进行保护的资源, 可以使用ignoring,使其跳过SpringSecurity
*
* 注:configure(HttpSecurity http)方法里的permitAll();也有类似的效果,
* 不过permitAll会走SpringSecurity,只是说无条件放行而已。
*/
web.ignoring().antMatchers("/picture/**");
web.ignoring().antMatchers("/md/**");
// 开发时,可以将SpringSecurity的debug打开
web.debug(true);
}
第二小步: 重写configure(HttpSecurity http)方法。
此方法相关的部分配置说明(未显示父类方法):
简单的自定义鉴权配置)示例:
/**
* SpringSecurity提供有一些基本的页面(如:login、logout等);如果觉得它提供的
* 基础页面难看,想使用自己的页面的话,可以在此方法里面进行相关配置。
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 访问 匹配以下ant的url不需要(非匿名)认证、不需要鉴权
http.authorizeRequests().antMatchers("/login", "/logout", "/logout/success", "/403", "/hello").permitAll();
// 只要认证通过,就可访问匹配以下ant的url。 (不论这人的权限是什么)
http.authorizeRequests().antMatchers("/index").authenticated();
/*
* 访问 匹配以下ant的url时, 需要至少有一个角色 "USER", "ADMIN" (需要鉴权)
*
* 注:[鉴权] 这个动作里面就隐含[认证]了, 因为只有认证后,才能拿到权限信息,才能进行鉴权;
* 如果连认证都没过的话,鉴权自然会失败。
*/
http.authorizeRequests().antMatchers("/user").hasAnyRole("USER", "ADMIN", "abc");
// 访问 匹配以下ant的url时, 需要至少有一个角色 "DBA", "ADMIN" (需要鉴权)
http.authorizeRequests().antMatchers("/dba").hasAnyRole("DBA", "ADMIN");
// 访问 匹配以下ant的url时, 需要有角色 "ADMIN" (需要鉴权)
http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN");
/*
* 设置任何请求都需要认证(除了前面.permitAll()的)。
*
* 注:如果不设置此项的话,那么对于那些未作任何配置的URL, 那么是默认 不认证、不鉴权的
*/
http.authorizeRequests().anyRequest().authenticated();
// 设置登录方式为 表单登录
http.formLogin();
/// 设置登录方式为 弹框登录
/// http.httpBasic();
/// 自定义登录页
/// http.formLogin().loginPage("myLoginPae");
/// 自定义登出页
/// http.logout().logoutUrl("myLogoutPae");
// 登出成功时,跳转至此url
http.logout().logoutSuccessUrl("/logout/success");
// 登录成功时,跳转至此url
// 注意:如果未登录,直接访问 登录失败页的话,会被DefaultLoginPageGeneratingFilter识别,并跳转至登录页进行登录
http.formLogin().successForwardUrl("/index");
// 登录失败时,跳转至此url
// 注意:如果未登录,直接访问 登录失败页的话,会被DefaultLoginPageGeneratingFilter识别,并跳转至登录页进行登录
http.formLogin().failureUrl("/login/failed");
/// 当鉴权不通过,是 跳转至此url
http.exceptionHandling().accessDeniedPage("/403");
}
注:上面代码中权限配置相关的方法,只示例了部分,完整的有:
第三小步: 重写configure(AuthenticationManagerBuilder auth)方法。
此方法相关的部分配置说明(未显示父类方法):
(配置几个用户,进行简单)示例:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 配置几个用户
auth.inMemoryAuthentication().withUser("user").password("user123").roles("USER");
auth.inMemoryAuthentication().withUser("dba").password("dba123").roles("DBA");
auth.inMemoryAuthentication().withUser("admin").password("admin123").roles("ADMIN");
// 配置这个用户的目的,是为了说明: 角色名瞎**起都可以
auth.inMemoryAuthentication().withUser("other").password("other123").roles("abc", "DBA");
}
注:角色名的定义并没有什么要求,瞎**写都可以。
提示: 本人这里为了快速简单演示,自定义了一个非常简单的PasswordEncoder实现;实际上,SpringSecurity对PasswordEncoder提供有大量实现,在实际开发时,如无特殊需求,完全可以使用SpringSecurity提供的PasswordEncoder实现类。
/**
* 自定义 加密器
*
* 注:只需要将其注册进入容器中即可,InitializeUserDetailsBeanManagerConfigurer类会从容器
* 拿去PasswordEncoder.class实现,作为其加密器
*
* @date 2019/12/21 17:59
*/
@Bean
public PasswordEncoder myPasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword == null ? "" : rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (rawPassword == null || rawPassword.length() == 0) {
return false;
}
return rawPassword.equals(encodedPassword);
}
};
}
测试流程:
测试user用户:
测试dba用户:
测试admin用户:
测试other用户:
注:创建这个other用户,主要是为了说明,角色名瞎**起都可以(比如此用户就有一个名为abc的角色)。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* SpringSecurity配置
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2019/12/7 14:08
*/
@Configuration
public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
/*
* 对于那些没必要进行保护的资源, 可以使用ignoring,使其跳过SpringSecurity
*
* 注:configure(HttpSecurity http)方法里的permitAll();也有类似的效果,
* 不过permitAll会走SpringSecurity,只是说无条件放行而已。
*/
web.ignoring().antMatchers("/picture/**");
web.ignoring().antMatchers("/md/**");
// 开发时,可以将SpringSecurity的debug打开
web.debug(true);
}
/**
* SpringSecurity提供有一些基本的页面(如:login、logout等);如果觉得它提供的
* 基础页面难看,想使用自己的页面的话,可以在此方法里面进行相关配置。
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 访问 匹配以下ant的url不需要(非匿名)认证、不需要鉴权
http.authorizeRequests().antMatchers("/login", "/logout", "/logout/success", "/403", "/hello").permitAll();
// 只要认证通过,就可访问匹配以下ant的url。 (不论这人的权限是什么)
http.authorizeRequests().antMatchers("/index").authenticated();
/*
* 访问 匹配以下ant的url时, 需要至少有一个角色 "USER", "ADMIN" (需要鉴权)
*
* 注:[鉴权] 这个动作里面就隐含[认证]了, 因为只有认证后,才能拿到权限信息,才能进行鉴权;
* 如果连认证都没过的话,鉴权自然会失败。
*/
http.authorizeRequests().antMatchers("/user").hasAnyRole("USER", "ADMIN", "abc");
// 访问 匹配以下ant的url时, 需要至少有一个角色 "DBA", "ADMIN" (需要鉴权)
http.authorizeRequests().antMatchers("/dba").hasAnyRole("DBA", "ADMIN");
// 访问 匹配以下ant的url时, 需要有角色 "ADMIN" (需要鉴权)
http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN");
/*
* 设置任何请求都需要认证(除了前面.permitAll()的)。
*
* 注:如果不设置此项的话,那么对于那些未作任何配置的URL, 那么是默认 不认证、不鉴权的
*/
http.authorizeRequests().anyRequest().authenticated();
// 设置登录方式为 表单登录
http.formLogin();
/// 设置登录方式为 弹框登录
/// http.httpBasic();
/// 自定义登录页
/// http.formLogin().loginPage("myLoginPae");
/// 自定义登出页
/// http.logout().logoutUrl("myLogoutPae");
// 登出成功时,跳转至此url
http.logout().logoutSuccessUrl("/logout/success");
// 登录成功时,跳转至此url
// 注意:如果未登录,直接访问 登录失败页的话,会被DefaultLoginPageGeneratingFilter识别,并跳转至登录页进行登录
http.formLogin().successForwardUrl("/index");
// 登录失败时,跳转至此url
// 注意:如果未登录,直接访问 登录失败页的话,会被DefaultLoginPageGeneratingFilter识别,并跳转至登录页进行登录
http.formLogin().failureUrl("/login/failed");
/// 当鉴权不通过,是 跳转至此url
http.exceptionHandling().accessDeniedPage("/403");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 配置几个用户
auth.inMemoryAuthentication().withUser("user").password("user123").roles("USER");
auth.inMemoryAuthentication().withUser("dba").password("dba123").roles("DBA");
auth.inMemoryAuthentication().withUser("admin").password("admin123").roles("ADMIN");
// 配置这个用户的目的,是为了说明: 角色名瞎**起都可以
auth.inMemoryAuthentication().withUser("other").password("other123").roles("abc", "DBA");
}
/**
* 自定义 加密器
*
* 注:只需要将其注册进入容器中即可,InitializeUserDetailsBeanManagerConfigurer类会从容器
* 拿去PasswordEncoder.class实现,作为其加密器
*
* @date 2019/12/21 17:59
*/
@Bean
public PasswordEncoder myPasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword == null ? "" : rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (rawPassword == null || rawPassword.length() == 0) {
return false;
}
return rawPassword.equals(encodedPassword);
}
};
}
}
入门级Spring Security学习完毕 !
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。