您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

前面运行写好的代码之所以没有任何显示,是因为还没有对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)的更多相关文章

  1. Spring Security(08)——intercept-url配置

    http://elim.iteye.com/blog/2161056 Spring Security(08)--intercept-url配置 博客分类: spring Security Spring ...

  2. Spring Security(三)

    Spring Security(三) 个性化用户认证流程 自定义登录页面 在配置类中指定登录页面和接收登录的 url @Configuration public class BrowserSecuri ...

  3. Spring Security(二)

    Spring Security(二) 注:凡是源码部分,我已经把英文注释去掉了,有兴趣的同学可以在自己项目里进去看看.:-) 定义用户认证逻辑 用户登录成功后,用户的信息会被 Security 封装在 ...

  4. Spring Security(一)

    Spring Security(一) 基本原理 前言 Spring Security核心功能 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) Srping Security基本原理 项目 ...

  5. 【权限管理系统】Spring security(三)---认证过程(原理解析,demo)

      在前面两节Spring security (一)架构框架-Component.Service.Filter分析和Spring Security(二)--WebSecurityConfigurer配 ...

  6. SpringBoot集成Spring Security(7)——认证流程

    文章目录 一.认证流程 二.多个请求共享认证信息 三.获取用户认证信息 在前面的六章中,介绍了 Spring Security 的基础使用,在继续深入向下的学习前,有必要理解清楚 Spring Sec ...

  7. SpringBoot集成Spring Security(6)——登录管理

    文章目录 一.自定义认证成功.失败处理 1.1 CustomAuthenticationSuccessHandler 1.2 CustomAuthenticationFailureHandler 1. ...

  8. SpringBoot集成Spring Security(5)——权限控制

    在第一篇中,我们说过,用户<–>角色<–>权限三层中,暂时不考虑权限,在这一篇,是时候把它完成了. 为了方便演示,这里的权限只是对角色赋予权限,也就是说同一个角色的用户,权限是 ...

  9. SpringBoot集成Spring Security(4)——自定义表单登录

    通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...

  10. SpringBoot集成Spring Security(2)——自动登录

    在上一章:SpringBoot集成Spring Security(1)——入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html二.两种实现方式 2. ...

随机推荐

  1. STL再回顾(非常见知识点)

    目录 为人熟知的pair类型 再谈STL 迭代器的使用 常用的STL容器 顺序容器 vector(向量) 构造方式 拥有的常用的成员函数(java人称方法) string 构造方式 成员函数 dequ ...

  2. 跨语言调用C#代码的新方式-DllExport

    简介 上一篇文章使用C#编写一个.NET分析器文章发布以后,很多小伙伴都对最新的NativeAOT函数导出比较感兴趣,今天故写一篇短文来介绍一下如何使用它. 在以前,如果有其他语言需要调用C#编写的库 ...

  3. 查找Linux下的大目录或文件

    目录 du -h --max-depth=1 du -h --max-depth=2 | sort -n du -hm --max-depth=2 | sort -n du -hm --max-dep ...

  4. 天翼云上新增IP备案具体操作步骤

    0.点击右上角的备案,进入到备案中心 1.已备案信息管理 点击左侧的已备案信息管理,右侧出现的页面中找到已备案网站信息,网站负责人后面的操作里有5个图标,点击第三个(变更接入),提交订单,进入到下一步 ...

  5. 阿里云SLB的健康检查配置

    若阿里云SLB健康检查异常,则默认SLB无法访问到后端ECS,也就意味着通过SLB访问后端ECS上部署的服务会报502 gateway. 另一种办法是关闭健康检查(不推荐) 简要说明: SLB通过配置 ...

  6. PAT (Basic Level) Practice 1006 换个格式输出整数 分数 15

    让我们用字母 B 来表示"百".字母 S 表示"十",用 12...n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 3 位的正整数. ...

  7. 源码学习之MyBatis的底层查询原理

    导读 本文通过MyBatis一个低版本的bug(3.4.5之前的版本)入手,分析MyBatis的一次完整的查询流程,从配置文件的解析到一个查询的完整执行过程详细解读MyBatis的一次查询流程,通过本 ...

  8. if、where、trim、choose、when、otherwise、foreach

    1.if if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行:反之标签中 的内容不会执行 <!--List<Emp> getEmpListBy ...

  9. 1.RabbitMQ系列之服务启动

    1. docker方式启动MQ # latest RabbitMQ 3.10 docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:156 ...

  10. Qt Quick 用cmake怎么玩子项目

    以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s/o-_aGqreuQda-ZmKktvxwA 以往在公司开发众多的项目中 ...