Spring Security(3)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
前面运行写好的代码之所以没有任何显示,是因为还没有对Spring Security进行配置,当然啥也不显示了。这就好比你坐在车上,却不打开发动机,车子当然跑不起来。所以咱们就来让它跑起来。不过在配置之前,有必要对Spring Security的登录流程做个大致了解。
如果深入源码去了解,这个玩意及其复杂,但是没必要,知道它的机制就行了。就好比你买车也不必把发动机拆开去看它是怎么工作的吧。简单来说它就是下面这些步骤:
1、Spring Security通过AuthenticationManager接口进行身份验证
2、ProviderManager是AuthenticationManager的一个默认实现
3、ProviderManager把验证工作委托给了AuthenticationProvider接口
4、AuthenticationProvider的实现类DaoAuthenticationProvider会检查身份认证
5、DaoAuthenticationProvider又把认证工作委托给了UserDetailsService接口
6、自定义UserDetailsService类从数据库中获取用户账号、密码、角色等信息,然后封装成UserDetails返回
7、使用Spring Security还需要自定义AuthenticationProvider接口,获取用户输入的账号、密码等信息,并封装成Authentication接口
8、将UserDetails和Authentication进行比对,如果一致就返回UsernamePasswordAuthenticationToken,否则抛出异常
下面是认证流程图:
首先重写loadUserByUsername:
- /**
- * 自定义用户详情
- *
- * @author 湘王
- */
- @Service("userDetailsService")
- public class CustomUserDetailsService implements UserDetailsService {
- @Autowired
- private UserService userService;
- @Autowired
- private RoleService roleService;
- @Autowired
- private UserRoleService userRoleService;
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- Collection<GrantedAuthority> authorities = new ArrayList<>();
- // 从数据库中取出用户信息
- SysUser user = userService.getByName(username);
- // 判断用户是否存在
- if(null == user) {
- System.out.println("user is not exist");
- throw new UsernameNotFoundException("user is not exist");
- }
- // 获得用户角色:方式一
- List<SysUserRole> list = userRoleService.getByUserId(user.getId());
- // // 获得用户角色:方式二
- // List<SysRole> list = roleService.getByUserId(user.getId());
- // // 给用户添加授权:方式一
- // for (SysUserRole userRole : list) {
- // SysRole role = roleService.getById(userRole.getRoleid());
- // authorities.add(new SimpleGrantedAuthority(role.getName()));
- // }
- // // 返回UserDetails实现类
- // return new User(user.getName(), user.getPassword(), authorities);
- // 给用户添加授权:方式二
- return User
- .withUsername(username)
- .password(user.getPassword())
- .authorities(list.stream()
- .filter(Objects::nonNull)// 判断是否为空
- .map(userRole -> roleService.getById(userRole.getRoleid()))// 从SysUserRole获取Role
- .map(SysRole::getName)// 转变为角色名称字符串
- .map(SimpleGrantedAuthority::new)// 依据角色名称创建SimpleGrantedAuthority
- .toArray(SimpleGrantedAuthority[]::new)// list转变为数组
- ).build();
- }
- }
因为UserDetailsService返回了封装的UserDetails,所以需要再自定义AuthenticationProvider返回Authentication接口:
- /**
- * 自定义登录验证
- *
- * @author 湘王
- */
- @Component
- public class CustomAuthenticationProvider implements AuthenticationProvider {
- @Autowired
- private CustomUserDetailsService customUserDetailsService;
- @Override
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- // 获取表单输入中返回的用户名
- String username = (String) authentication.getPrincipal();
- // 获取表单中输入的密码
- String password = (String) authentication.getCredentials();
- // 这里调用我们的自己写的获取用户的方法
- UserDetails userInfo = customUserDetailsService.loadUserByUsername(username);
- if (userInfo == null) {
- System.out.println("user is not exist");
- throw new UsernameNotFoundException("user is not exist");
- }
- PasswordEncoder passwordEncoder = new PasswordEncoder() {
- @Override
- public String encode(CharSequence charSequence) {
- return charSequence.toString();
- }
- @Override
- public boolean matches(CharSequence charSequence, String s) {
- return s.equals(charSequence.toString());
- }
- };
- // 采用简单密码验证
- if (!passwordEncoder.matches(password, userInfo.getPassword())) {
- System.out.println("user or password error");
- throw new BadCredentialsException("user or password error");
- }
- Collection<? extends GrantedAuthority> authorities = userInfo.getAuthorities();
- // 构建返回的用户登录成功的token
- return new UsernamePasswordAuthenticationToken(userInfo, password, authorities);
- }
- @Override
- public boolean supports(Class<?> aClass) {
- return true;
- }
- }
接着来实现实现WebSecurityConfigurerAdapter,它通过重写WebSecurityConfigurerAdapter中的相关方法(一般是configurer)来自定义配置。WebSecurityConfigurerAdapter主要做几件事:
1、初始化
2、开启Security
3、配置各种过滤器,实现验证过滤器链
下面是它的代码:
- /**
- * spring security验证配置
- *
- * @author 湘王
- */
- // 配置类
- @Configuration
- // 开启Security服务
- @EnableWebSecurity
- // 开启全局Securtiy注解
- @EnableGlobalMethodSecurity(prePostEnabled = true)
- public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
- @Autowired
- private CustomUserDetailsService customUserDetailsService;
- @Autowired
- private CustomAuthenticationProvider authenticationProvider;
- // 自定义的登录验证逻辑
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.authenticationProvider(authenticationProvider);
- }
- // 控制逻辑
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- // 执行UsernamePasswordAuthenticationFilter之前添加拦截过滤
- http.addFilterBefore(new CustomInterceptorFilter(), UsernamePasswordAuthenticationFilter.class);
- http.authorizeRequests()
- .anyRequest().authenticated()
- // 设置自定义认证成功、失败及登出处理器
- .and().formLogin().loginPage("/login")
- .and().cors()
- .and().csrf().disable();
- }
- @Override
- public void configure(WebSecurity web) throws Exception {
- // 设置拦截忽略文件夹,可以对静态资源放行
- web.ignoring().antMatchers("/css/**", "/js/**");
- }
- }
接着用postman进行测试:
回顾整个调用过程,它的时序图是:
但是等等:好像除了/login,其他方法都不能正常访问!
感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~
Spring Security(3)的更多相关文章
- Spring Security(08)——intercept-url配置
http://elim.iteye.com/blog/2161056 Spring Security(08)--intercept-url配置 博客分类: spring Security Spring ...
- Spring Security(三)
Spring Security(三) 个性化用户认证流程 自定义登录页面 在配置类中指定登录页面和接收登录的 url @Configuration public class BrowserSecuri ...
- Spring Security(二)
Spring Security(二) 注:凡是源码部分,我已经把英文注释去掉了,有兴趣的同学可以在自己项目里进去看看.:-) 定义用户认证逻辑 用户登录成功后,用户的信息会被 Security 封装在 ...
- Spring Security(一)
Spring Security(一) 基本原理 前言 Spring Security核心功能 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) Srping Security基本原理 项目 ...
- 【权限管理系统】Spring security(三)---认证过程(原理解析,demo)
在前面两节Spring security (一)架构框架-Component.Service.Filter分析和Spring Security(二)--WebSecurityConfigurer配 ...
- SpringBoot集成Spring Security(7)——认证流程
文章目录 一.认证流程 二.多个请求共享认证信息 三.获取用户认证信息 在前面的六章中,介绍了 Spring Security 的基础使用,在继续深入向下的学习前,有必要理解清楚 Spring Sec ...
- SpringBoot集成Spring Security(6)——登录管理
文章目录 一.自定义认证成功.失败处理 1.1 CustomAuthenticationSuccessHandler 1.2 CustomAuthenticationFailureHandler 1. ...
- SpringBoot集成Spring Security(5)——权限控制
在第一篇中,我们说过,用户<–>角色<–>权限三层中,暂时不考虑权限,在这一篇,是时候把它完成了. 为了方便演示,这里的权限只是对角色赋予权限,也就是说同一个角色的用户,权限是 ...
- SpringBoot集成Spring Security(4)——自定义表单登录
通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...
- SpringBoot集成Spring Security(2)——自动登录
在上一章:SpringBoot集成Spring Security(1)——入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html二.两种实现方式 2. ...
随机推荐
- e1000e网卡驱动在麒麟3.2.5上编译安装
一.清空原驱动 因为系统安装完毕后系统中自带了e1000e的网卡驱动,会影响后面自行编译的驱动 所以先用find命令找出并删除掉所有关于e1000e的驱动文件 find / -name "* ...
- File类、FileOutputStream
day01 File类 File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径) 使用File可以做到: 1:访问其表示的文件或目录的属性信息,例如:名字,大小, ...
- IO_对象流
对象流 对象的本质是用来组织和存储数据的,对象本身也是数据.那么,能不能将对象存储到硬盘上的文件中呢?能不能将对象通过网络传输到另一个电脑呢?我们可以通过序列化和反序列化实现. java对象的序列化和 ...
- 新增一个Redis 从节点为什么与主节点的key数量不一样呢?
在日常的 Redis 运维过程中,经常会发生重载 RDB 文件操作,主要情形有: 主从架构如果主库宕机做高可用切换,原从库会挂载新主库重新获取数据 主库 QPS 超过10万,需要做读写分离,重新添加从 ...
- http服务(postman调用方法及反参)
#region 监听url #region 监听url路径请求 static HttpListener httpobj; private void listeningUrl() { //提供一个简单的 ...
- 《Java基础——线程类》
Java基础--线程类 一.线程的创建之Thread类: 规则: 通过声明一个新类作为子类继承 Thread 类,并复写 run() 方法,就可以启动新线程并执行自己定义的 run()方法 ...
- Java SE 19 新增特性
Java SE 19 新增特性 作者:Grey 原文地址: 博客园:Java SE 19 新增特性 CSDN:Java SE 19 新增特性 源码 源仓库: Github:java_new_featu ...
- 使用NextCloud搭建私有网络云盘并支持Office文档在线预览编辑以及文件同步
转载自:https://www.bilibili.com/read/cv16835328?spm_id_from=333.999.0.0 0x00 前言简述 描述:由于个人家里的NAS以及公司团队对私 ...
- 路径参数和数值校验: Path_Parameters_and_Numeric_Validations
官方文档地址: https://fastapi.tiangolo.com/zh/tutorial/path-params-numeric-validations/ # -*- coding: UTF- ...
- 使用nginx代理nexus,不是/根路径
location /nexus/ { proxy_pass http://192.168.0.218:8081/; proxy_set_header Host $host:$server_port; ...