SpringSecurity

1.主要作用是 认证和授权
2.底层是过滤器链
3.导入 springSecurity 场景启动器后,spring启动,自动配置生效

过滤器如何加载的

	1.SecurityFilterAutoConfiguration
		@bean
		Delegating FilterProxyRegistrationBean(注册了 DelegatingFilterproxy(filter))
		执行它的 doFilter()

		delegateTouse = this.initDelegate(webApplcaiitonContext)
		Filter delegate = wac.getBean(filterChainproxy,Filterclass)
		创建 filterchainProxy实例并获得
		delegate.init(this.getFilterconfig())

		执行filterchainproxy的 dofilter() 
		filterchainproxy里面有个 list<SecurityFilterChain>里面有关于security的全部过滤器

		filterchainProxy.doFilter()
		doFilterInternal()
		List<Filter> filters = this.getFilters()
		
		遍历List<SecurityFilterchain>
		if(chain.matches(request)){
			return chain.getFilters()
		}能匹配 request的 filter全部 返回
		后将这些 filter全部 加到我们的 filterchain中

	======================================================
	delegatingFilter 的 doFilter 就是获得 filterchain(里面包含那10几个 security的 filter)
	注意,这个delegatingFilter的 doFilter是 在springboot容器启动就执行的,目的就是
	将Filter全部加到 filterchain中,便于后面过滤请求

重要的三个过滤器

1.FilterSecurityInterceptor
是一个方法级的 权限过滤器,基本位于 过滤器的 最底部

	1 dofilter()
	   fi = new FilterInvocation()
	   invoke(fi)
	   判断上一个 filter的 doFilter是否 执行了 chain.doFilter() 执行了
		 fi.getchain().doFilter()

	它的doFilter的意思,就是判断上一个 filter的 chain.doFilter()是否执行
	执行了,那么这个filter 直接 执行下一个filter 的 doFilter()

2.ExceptionTranslationFilter
是一个异常过滤器,用来处理在认证过程中抛出的异常

	1. doFilter()
		try{
			chain.doFilter()
		}catch(Exp e){
			throw e;抛出异常
		}
	在下面过滤中,认证和授权,是在下面的过滤链中完成的,
	只要下面的过滤出现了异常,那么在这一层捕捉

3.usernamePasswordAuthenticationFilter
/loginpost请求 做拦截,检验表单的 用户名密码 是否
正确

	1.dofilter()
		authResult = attemptAuthentication(req,resp)'
		if authResult = null return filterchain直接结束
		else sessionStrategy.onAuthentication(authResult,req,resp) 

    2.所以,我们这里 关注 attemptAuthentication()即可
      但是,这里的是默认的校验,我们需要 写一个 usernamePasswordAuthenticationFilter的 子类
      并且 重写 attemptAuthentication()方法,完成自定义username,password校验

	3.重写的 attempAuthentication()
		1. 判断 是否是 post请求 不是 直接 return
		
		2. 得到 request中的 username和 password
		
		3. 注意:前端传过来的 参数名 必须是 username和 password
		   因为,我们这过滤器已经写死了
		   
		4.UserDetaliService接口实现类loadUserByUsername() 查询 datebase 中的 username和password
		  如果查询得到,那么封装成 User(Security提供的)返回,user中包括了 权限和角色
		  
		5.用passwordEncoder接口 将前端的password加密后,和user的 password作比较
		  如果相等,那么认证成功

		6.userDetailService只负责返回User,或者直接return,或者抛异常(因为user有可能查询不到
		那就没有后面 认证成功的需要了,直接在这里结束即可)
		后面的 认证 包括用passwordEncoder给 前端密码加密,都是springSecurity做的,他负责判断是否
		认证成功

		7.认证成功,跟授权没有半毛钱,认证成功代表 User登入了,授权只是说,这个User有没有访问这个
		路径的权限,但是登入是已经登入成功了的,下一次访问无需再次认证

两个重要接口

	1.UserDetialsService接口
		UserDetalis loadUserByUsername(String name)
		在这个方法里面查用户,并判断调用 PasswordEncoder的matchs方法
		判断密码是否正确,最后 return User(user)
		
	2.PasswordEncoder接口
		encode(password) 将密码加密
		mathces(password)方法,将加密的方法,和 user的password作比较
		相等,return true
		
	BCryptPasswordEncoder 是 Spring Security 官方推荐的密码解析器,平时多使用这个解析器。

	重点:userDetailService的作用,就是返回 一个User,它的调用不用我们管
	返回User后,再跟前端传来的做比较,这一步也不归我们管
	同样PasswordEncode给前端 密码加密,也不归我们管,我们只用在
	auth里面提供,userDetailService,和passwordEncode就行


	3.就算我们不 重写 一个 usernamepasswordAuthenticationFilter
	  我们就写注册 一个 passwordEncoder的实现类,重写里面里面的方法
	  在默认的 filter中也会,调用 它的 encode方法,给密码加密
	  然后再比较
	
	4.给前端密码加密,是springSecurity帮我们做的,不用我们自己做,我们只用提供在配置类的configure方法里面提供,
	  password接口即可

passwordEncoder使用时机的详解

	1.springSecurity有一个默认的passwordEncoder
	
	2.在User返回后,springSecurity会调用 passwordEncoder的 matches方法,去匹配User里面的password
	  和前端传来的password(当然我们需要对前端传来的 password加密)
	
	3. passwordEncoder的2个方法
		1.String encode(CharSequence charSequence 这个是对前端password的封装)
			这个方法,如果是我们提供的 passwordEncoder,完全可以不用
			因为springSecurity只会调用 matches方法,只是默认的passwordEncoder会在 matches方法里面
			调用encode() 方法,去给 前端passworde 加密
			
		2.boolean matches(CharSequence charSequence , String encodedpassword)
			charSequene 代表 前端password的封装,一般要charSequence.toString(),再去加密
			encodedpassword 是 dataBase中 存储的password(一般都是加密了的)
			我们需要在这个方法将 charSequence.toSrting做一个加密后和 encodedpassword做一个比较
			然后 return boolean,如果 return true 代表 认证成功

			注意:加密方式需要和 database中储存的password的加密方式一样

web权限方案

1.用户认证
这三种方式本质都是在 auth里面设置用户名密码,角色,权限
或者设置,userDetailService,PasswordEncoder,
真正 拿User 和 前端的 作比较…不用我们管

	1.配置文件,修改默认username 和 password
		spring.security.user.name=username
		spring.security.user.password=password
	这样默认用户名密码就改了,这样执行到 filter的时候,就会用
	前端的用户名和密码 和 这个改了的 去比较

	2.配置类
		在springbootWebSecurityCOnfiguration中
			默认支持 DefaultConfigurerAdapter
			前提是在 缺少 WebSecurityConfigureAdapter的情况下
		现在我们自己注册一个,WebSecurityConfigurerAdapter的实现类
		就可以用我们自己的

		重写 void configure(AuthenticationManagerBullder auth)方法
		这个方法,可以设置我们的 默认用户名,密码,roles
		auth.inMemoryAuthentication().writerUser().password().roles();

	3.自己编写,userDetialsService和passwordEncoder(最常用)
		1.将userDetialsService和passwordEncoder 注入ioc容器中
		
		2.在配置类中 autowired这两个组件
		
		3.在配置类的 void configurer(AuthenticationManangerBuilder auth)中
		  auth.userDetailsService().passwordEncoder(),将这两个组件 set进 auth
		  
		4.这样,我们就可以在 userDetailsService中完成 User的 return(不能return user,那后面的认证都不需要了
		  直接结束)
		  User返回后,后面passwordEncoder给前端密码加密,然后认证这不是我们需要管的
		  我们要做的 就是在 userDetailsService中,将User返回

User

	代表了,return的用户,里面有用户的userName,password,以及List《GrantedAuthority》
	注意 GrantedAuthority代表 auth,相当于代表Role和权限(Authority),List《GrantedAuthorit》就代表了,
	这个User,拥有这个 Role/权限的 集合

认证和授权是两个方面的,返回User,然后SpringSecurity去认证,认证时不看角色和权限,就看用户名和密码是否对应,是,代表认证成功,代表登入了,User中的(角色和权限),代表User的角色和权限,授权是 配置类的configure(HttpSecurity)中设置的,角色权限不通过,代表不能访问此路径,但是认证是通过了的,下次访问角色和权限允许的那就可以访问了,但是不用再次认证

关于配置类中的,configure(HttpSecurity http)和configure(AuthticationManangerBuilder auth)的区别

	1.configure(AuthticationManangerBuilder auth)里面主要是设置,我们返回User的实现类,已经将前端密码加密的
	  passwordEncoder,换句话说,就是设置我们要给springSecurity做认证的 User

	2.configure(HttpSecurity http)里面主要是设置,在认证的过程中的一些 SpringSecurity的功能的一些设置
	比如,设置登入页面,登入成功后跳转的路径,哪些路径不需要认证,哪些路径需要权限.....

configure(HttpSecurity http)里面一些具体设置

(loginPage("/index") // 配置哪个 url 为登录页面
.successForwardUrl("/success") // 登录成功之后跳转到哪个 url
.failureForwardUrl("/fail");// 登录失败之后跳转到哪个 url,

上面三个是说,如果请求直接 访问登入页面,那么登入成功即认证成功后跳转到哪个页面)
(如果是,直接访问的 请求地址,中间需要做认证,认证成功后,就会直接访问请求地址****了,不会再跳转到成功页面了)

	protected void configure(HttpSecurity http) throws Exception {
	
		//登入设置
		http.formLogin()
		
		.loginPage("/index") // 配置哪个 url 为登录页面
		.successForwardUrl("/success") // 登录成功之后跳转到哪个 url
		.failureForwardUrl("/fail");// 登录失败之后跳转到哪个 url
		(上面三个,是说,如果请求直接 访问登入页面,那么登入成功即认证成功后跳转到哪个页面)
		(如果是,直接访问的 请求地址,中间需要做认证,认证成功后,就会直接访问请求地址了,不会再跳转到成功页面了)
		
		//关于 认证路径,和权限角色设置
		http.authorizeRequests()
		
		.antMatchers("/layui/**","/index").permitAll()  //表示配置请求路径无需认证
		
		.antMatchers("/layui/**","/index").hasRole("") 
			表示User只能有 这一个角色(User中的 GrantedAuthority只能是 一个这个角色才能授权访问)
			
		.antMatchers("/layui/**","/index").hasAnyRole("","") 
			表示User可以有这其中的 任意一个角色即可
			
	(注意配置文件中不需要添加”ROLE_“,因为上述的底层代码会自动添加与之进行匹配)
	(但是,new GrantedAuthority("ROLE_"+"")这个必须加上ROLE,才能和springSecurity的比较
	  因为spirngSeucrity底层.antMatchers("/layui/**","/index").hasRole("")  是将""加上了ROEL_ 
	  再和 User中的 GrantedAuthority("") 中的 ""比较的 )
		=================================================================		
				
		.antMatchers("/layui/**","/index").hasAuthority("")
			表示User只能有 这一个权限(User中的 GrantedAuthority只能是 一个这个权限才能授权访问)
			
		.antMatchers("/layui/**","/index").hasAnyAuthority("","")
			表示User可以有这其中的 任意一个权限即可
			
		.anyRequest().authenticated();   // 其他请求需要认证
		
		
		// 关闭 csrf
		http.csrf().disable();
		}

(注意配置文件中不需要添加”ROLE_“,因为上述的底层代码会自动添加与之进行匹配)
(但是,new GrantedAuthority(“ROLE_”+"")这个必须加上ROLE,才能和springSecurity的比较
因为spirngSeucrity底层.antMatchers("").hasRole("") 是将"“加上了ROEL_
再和 User中的 GrantedAuthority(”") 中的 ""比较的 )

用户注销

	1.在配置文件的 	protected void configure(HttpSecurity http) 中
	  http.logout.logoutUrl("注销地址").logoutSuccessUrl("注销成功地址").permitAll();
	  注销地址不是任何资源,只是一个url字符串,在页面设置这个 url,
	  你点击,就会注销成功,并跳转到注销成功的地址
	
	2.当你注销成功后,你的User相当于被注销了,没有User了,下次得再次 认证

	3.用户注销,实际上调用的是tokenMananger的 移除cookie中(或者header中的cookie),那么下次访问的时候
	无法获得token字符串,那么就算用户注销了,就得重新认证了

认证成功后,再次访问其他路径,就不用再次认证了,除非关闭浏览器

spring实现自动登入(浏览器关闭,也能自动登入)

技术点:cookie+springSecurity机制实现自动登入
在这里插入图片描述
注意:在登入页面添加 自动登入复选框,name必须是 remember-mc
我们只需要完成上述配置,其他的springSecurity帮我们做了

自动登入底层原理
在这里插入图片描述
首先,不管我们有没有配置自动登入,我们都会走上面这个流程,都会生成token字符串,都会加入到cookie中…,只是一点我们配置配的是啥,就是配置的 cookie的有效时间

	1.添加复选框,我们勾选了,传了 remember-me,参数,代表可以走下面的 自动登入的流程了
	2.在配置类中配置,PersisterTokenReposity组件,因为SpirngSecurity底层在 userDetailsService认证成功后
	  会调用 这个 组件去保存cookie,和 存数据库
	3.在 配置类的 cofigue(HttpSecurity)方法中
	  设置 persisterTokenReposity和cookie时长,以及userDetailsService,代表 PersisterTokenReposity是在
	  userDetalsService中 执行的

认证和授权是两个方面的,返回User,然后SpringSecurity去认证,认证时不看角色和权限,就看用户名和密码是否对应,是,代表认证成功,代表登入了,User中的(角色和权限),代表User的角色和权限,授权是 配置类的configure(HttpSecurity)中设置的,角色权限不通过,代表不能访问此路径,但是认证是通过了的,下次访问角色和权限允许的那就可以访问了,但是不用再次认证,因为cookie的时间没有过期,每次都能将cookie中的token和 dataBase中的比较一样,就免去了再次认证

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值