一,简介
最近新换了一家公司,使用的是SpringBoot+SpringSecurity+Restful+Redis+Mybatis为后台框架
这里主要针对SpringBoot及相关框架展开学习讨论
二,SpringSecurity
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
三,SpringBoot中集成SpringSecurity
首先在pom.xml中引入SpringSecurity
创建WebSecurityConfig类继承WebSecurityConfigurerAdapter
首先看CustomUserDetailsService,这个类里面终于一个方法,就是loadUserByUsername(String userName)在Security中有4中实现方式
1.配置文件实现,只需要在配置文件中指定拦截的url所需要权限、配置userDetailsService指定用户名、密码、对应权限,就可以实现。
2.实现UserDetailsService,loadUserByUsername(String userName)方法,根据userName来实现自己的业务逻辑返回UserDetails的实现类,需要自定义User类实现UserDetails,比较重要的方法是getAuthorities(),用来返回该用户所拥有的权限。
3.通过自定义filter重写spring security拦截器,实现动态过滤用户权限。
4.通过自定义filter重写spring security拦截器,实现自定义参数来检验用户,并且过滤权限。
很显然第一种方式在配置文件中设定用户名,密码,权限是不满足我们的要求的,基本上现在项目都是通过数据库获取到用户信息,然后通过权限对资源进行管理,不会在配置文件中写死用户数据,也很少通过导入XML文件从里面获取用户信息,所以第一种方式PASS,今天我们先说说第二种实现方式,第三,四种实现方式我们以后再说
在loadUserByUsername(String userName)方法中,我们可以获取到用户名称通过用户名称我们调用自己Service中的方法,在数据库中查找是否存在这个用户名的用户,如果有的话我们返回User(Security中的用户对象),也可以放回我们自定义的实体User,不过需要实现UserDetails这个接口,这里我们现返回Security中的User对象,当我们在数据库中没有查询到该用户时,我们需要抛出UsernameNotFoundException告知前台你的用户名不对。
可以看到我们返回了一个User对象并使用了他的有参构造用户名,密码,权限
这是UserDetailsService源码我们可以看到除了用户名,密码,权限,还有其他的属性,具体项目大家可以根据需求创建自己的数据库表和相应的实体类,例如有的项目中需要账户是否在黑名单中,如果在黑名单则不可以访问资源,我们就可以使用isAccountNonLocked这个属性进行判断,在数据库中获得用户是否在黑名单中如果在返回false,如果不在返回true,然后根据相关异常告诉前台这个用户被锁定了,在黑名单中其他几个数据用法也一样,如果你不需要使用这几个属性的话,可以再自己的用户类中直接返回true,默认通过
到这里可能有的人会问,我们只是通过了用户名去和数据库比对,难道说只要用户名正确了,我们密码错误或者说密码为空我们也可以登录成功?接下来我们看看Security在执行loadUserByUsername这个方法后去了哪里,在这个方法执行完后Security会把User对象返回到ProviderManager中通过SecurityContextHolder.getContext().setAuthentication();这个方法吧用户信息保存在SecurityContextHolder以后我们需要获取当前用户信息的是够也是从SecurityContextHolder中获取,此时用户信息交给SecurityContextHolder来进行管理并进入UsernamePasswordAuthenticationFilter这个过滤器进行验证
UsernamePasswordAuthenticationFilter中的attemptAuthentication方法在attemptAuthentication方法中attemptAuthentication方法将表单请求的信息(用户、密码等信息)赋值给UsernamePasswordAuthenticationToken(authRequest)然后调用getAuthenticationManager().authenticate(authRequest)对用户密码的正确性进行验证,认证失败就抛出异常,成功就返回Authentication对象。
到了这里我们最简单的登录验证已经做好了,本人也是刚刚学习这个框架,也希望大家及时纠错和分享自己的学习成果
网友评论