

1. Spring Security 是一个提供身份验证,授权,保护以及防止常见攻击的框架,由于同时支持响应式和命令式,是spring框架的安全标准。
前提条件
jdk1.8+
例子使用SpringBoot版本 【2.0.5.RELEASE】,代码都是简写,只写关键代码,源码demo,文章底部github
1. 引入maven jar包(正常添加jar包依赖,只需保留第一步的jarbao,第三步第四步忽略即可)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
2. 因为SpringBoot提供了BOM来管理版本,因此不需要指定版本,如果我们需要指定版本可以通过配置maven属性来配置
例
<properties><!-- ... --><spring-security.version>5.2.2.BUILD-SNAPSHOT</spring-security.version></dependencies>
3. 如果使用SNAPSHOT版本则需要定义Spring Snapshot存储库
<repositories><!-- ... possibly other repository elements ... --><repository><id>spring-snapshot</id><name>Spring Snapshot Repository</name><url>https://repo.spring.io/snapshot</url></repository></repositories>
4. 如果使用里程碑版本或者候选的版本,则需要指定Spring Milestone存储库
<repositories><!-- ... possibly other repository elements ... --><repository><id>spring-milestone</id><name>Spring Milestone Repository</name><url>https://repo.spring.io/milestone</url></repository></repositories>
5. application.properties 配置属性内容
# 启动端口server.port=8081# 启动项目路径server.servlet.context-path=/simple-security
6. 此时简单版的demo就已经完成了,访问http://127.0.0.1:8081会重定向到http://127.0.0.1:8081/simple-security/login 页面显示内容如下

7. 默认的用户名:user,密码为控制台打印的uuid

8.此时我们输入用户名密码之后验证通过了,但是会显示404,这是因为我们没有配置登录成功的首页,现在开始配置首页
9.新建一个WebSecurityConfig配置类,继承
WebSecurityConfigurerAdapter,此处配置关闭了csrf,支持表单登录,
拦截/login登录的请求,登录成功跳转login-success
代码如下
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {protected void configure(HttpSecurity http) throws Exception {// 屏蔽csrf跨站http.csrf().disable()// 支持表单登录.formLogin()// 登录逻辑处理url.loginProcessingUrl("/login")// 登录页面// .loginPage("login-view")//自定义成功登录页面.successForwardUrl("/login-success");}/*** 密码验证方式* NoOpPasswordEncoder.getInstance() 字符串校验* @return*/public PasswordEncoder passwordEncoder(){return NoOpPasswordEncoder.getInstance();}}
10. 配置一个WebMvcConfig,重定向我们的url,实现登录逻辑处理
public class WebMvcConfig implements WebMvcConfigurer {public void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("redirect:/login");}}
11. 编写一个controller,作为登录成功之后的跳转
public class LoginController {public String login(){return "login success";}}
12.此时启动项目,访问http://127.0.0.1:8081/simple-security/login,输入用户名user,密码(控制台打印的uuid)登录成功即可看到打印的login success

13. 自定义用户,实现UserDetailsService,此处我们生成的用户名是tz,密码就是123,我们实际使用中,可以根据用户名在数据库中查找返回,此处为了方便直接设置了一下,没有进行数据库查询。这样我们就成功配置了一个用户名tz密码123的账号,现在就来登录试一下吧
public class MyUserDetailService implements UserDetailsService {public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {UserDetails userDetails = User.withUsername("tz").password("123").build();return userDetails;}}
14.浏览器打开输入http://127.0.0.1:8081/simple-security/login
账号tz,密码123,点击login,登录成功跳转到我们刚才定义的controller,密码太简单了,我们平常不能直接使用明文密码啊,一般都是加密的,先看上面的WebSecurityConfig中我们定义了
PasswordEncoder的Bean 我们返回了一个
NoOpPasswordEncoder.getInstance()
这个代表进行简单的字符串匹配,也就是字符串相等就OK,我们下面配置另一个加密,BCryptPasswordEncoder(),修改我们的WebSecurityConfig
/*** 密码验证方式* NoOpPasswordEncoder.getInstance() 字符串校验* @return*/public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
15.新建一个test类,生成我们的Bcrypt加密的密码,方便一会我们测试
public class SimpleSecurityApplicationTests {public void contextLoads() {String hashpw = BCrypt.hashpw("123", BCrypt.gensalt());System.out.println(hashpw);}// 打印结果 $2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG// 这个字符串就代表123,上面我们是使用的随机盐的方式,每次生成的密码都不一样,但是校验时原密码都是123}
下面把打印的结果替换到我们的MyUserDetailService中
修改结果如下
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {UserDetails userDetails = User.withUsername("tz").password("$2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG").build();return userDetails;}
16. 启动项目,继续使用用户tz密码123登录,此时也是显示登录成功
17. 下面展示一下基本的授权
Controller中新增资源url
public String r1(){return "r1";}public String r2(){return "r2";}
WebSecurityConfig增加对资源的拦截,此处访问/r/r1需要p1权限,访问/r/r2需要p2权限
// 屏蔽csrf跨站http.csrf().disable().authorizeRequests()// 拦截/r/**请求需要认证.antMatchers("/r/r1").hasAuthority("p1").antMatchers("/r/r2").hasAuthority("p2").antMatchers("/r/**").authenticated()// // 除了/r/** 其他都可以访问.anyRequest().permitAll().and()// 支持表单登录.formLogin()// 登录逻辑处理url.loginProcessingUrl("/login")//自定义成功登录页面.successForwardUrl("/login-success");}
MyUserDetailService中给tz用户增加p1权限
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {UserDetails userDetails = User.withUsername("tz").password("$2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG").authorities("p1").build();return userDetails;}
18.此时基本的权限拦截就完成了,如需更复杂的请参考官网验证,下面演示一下浏览器访问http://127.0.0.1:8081/simple-security/login使用用户名tz密码123来进行登录

修改为r1的访问url,访问查看我们 已经读取到r1 的资源

修改为r2的访问URL,访问查看我们已经被拒绝,显示403,因为我们只有p1权限,访问r1需要p1权限,所以我们可以访问,访问r2需要p2权限,我们没有p2权限,所以拒绝我们的访问

19. 好了入门教程到此结束了,如有错误欢迎指出
github demo地址 https://github.com/TianPuJun/springboot-demo/tree/master/springboot-simple-security
官网 https://spring.io/projects/spring-security
参考https://docs.spring.io/spring-security/site/docs/5.2.2.BUILD-SNAPSHOT/reference/htmlsingle/
原文作者:醉鱼Java;如有侵权,请联系管理员删除。