赞
踩
SpringSecurity主要是通过过滤器来实现功能的!我们要找到SpringSecurity实现认证和校验身份的过滤器!
用户认证: 使用UsernamePasswordAuthenticationFilter 过滤器中attemptAuthentication方法实现认证功能,该过滤器父类中successfulAuthentication方法实现认证成功后的操作。
身份校验: 使用 BasicAuthenticationFilter 过滤器中doFilterInternal方法验证是否登录,以决定能否进入后续过滤器。
用户认证:
由于是前后端分离,项目架构设计是分布式的,我们要满足可以接受异步post的认证请求参数,需要修改UsernamePasswordAuthenticationFilter过滤器中attemptAuthentication方法,让其能够接收请求体。 另外,默认successfulAuthentication方法在认证通过后,是把用户信息直接放入session就完事了,现在我们需要修改这个方法,在认证通过后生成token并返回给用户。
身份校验
使用BasicAuthenticationFilter 过滤器中 doFilterInternal方法 校验用户是否登录,就是看session中是否有用户信息,我们要修改为,验证用户携带的token是否合法,并解析出用户信息,交给SpringSecurity,以便于后续的授权功能可以正常使用。
权限框架SpringSecurity 前后端分离登录 (BasicAuthenticationFilter)
https://blog.csdn.net/zxd1435513775/article/details/124801891
// 自定义AuthenticationManager
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
}
认证管理器,负责验证,认证成功后,AuthenticationManager 返回一个填充了用户认证信息(包括权限信息、身份信息、详细信息等,但密码通常会被移除)的 Authentication 实例。
然后再将 Authentication 设置到 SecurityContextHolder
容器中。
AuthenticationManager 接口是认证相关核心接口,也是发起认证的入口。但它一般不直接认证,其常用实现类 ProviderManager 内部会维护一个List<AuthenticationProvider>
列表,存放多种认证方式,默认情况下只需要通过一个 AuthenticationProvider 的认证,就可以认为是登录成功。
加载登录账户 loadUserByUsername
https://blog.csdn.net/u012811805/article/details/118401750
链接:https://blog.csdn.net/wwang_dev/article/details/119107355
// 执行登录认证过程
Authentication authentication = authenticationManager.authenticate(token);
// 认证成功存储认证信息到上下文
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成令牌并返回给客户端
String genToken = JwtTokenUtils.generateToken(authentication);
token.setToken(genToken);
// 保存权限到redis
redisTemplate.opsForValue().set(genToken, JSONArray.toJSONString(authentication.getAuthorities()));
return token;
从这里也可以看出为什么 pinciple 和 credentials 的类型都是 Object,因为 pinciple 认证前需要传 String 类型的 username,认证后需要传实现了UserDetails 接口的用户对象;而 credentials 认证前需要传前端传来的String类型的password,认证后需要传 String类型的密码 或者 null。
通常都是,接收 前端传来的 username 和 password,调用 两个参数的构造器,创建一个未认证的对象,交给AuthenticationManager进行认证。认证成功后,调用三个参数的构造器,创建一个已认证的对象。
@Order(10) @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig2 extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; //认证服务器 配置用户认证 // 使用自定义身份验证组件 //指定密码加密策略 @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { // auth.userDetailsService(userDetailsService); auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService)); } }
改造 WebSecurityConfiguration 加载自定义UserDetailsService
根据用户名获取用户的权限,链接:https://blog.csdn.net/tiancxz/article/details/108856337
//返回一个自定义数据库获取用户权限的实现
@Autowired
public UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
每次获取token时,都会进入自定义实现从数据库获取权限
http://client:secret@localhost:10101/oauth/token
There is no PasswordEncoder mapped for the id “null”
史上最简单的Spring Security教程(二十六):DaoAuthenticationProvider详解
https://blog.csdn.net/liuminglei1987/article/details/108279836
说到 Authentication 相信都不陌生。最著名的,便是 UsernamePasswordAuthenticationToken。
而 DaoAuthenticationProvider 是用于解析并认证 UsernamePasswordAuthenticationToken 的这样一个认证服务提供者。
其最终目的,就是根据 UsernamePasswordAuthenticationToken,获取到 username,然后调用 UserDetailsService 检索用户详细信息。
在其基类 AbstractUserDetailsAuthenticationProvider 中,需要子类实现 retrieveUser() 、additionalAuthenticationChecks() 等抽象方法。
1、用户通过浏览器访问A系统被保护的资源链接
2、A系统判断当前会话是否登录,如果没有登录则跳转到A系统登录地址/login
3、A系统首次接收到/login请求时没有state和code参数,此时A系统拼接系统配置的单点登录服务器授权url,并重定向至授权链接。
4、单点登录服务器判断此会话是否登录,如果没有登录,那么返回单点登录服务器的登录页面。
5、用户在登录页面填写用户名、密码等信息执行登录操作。
6、单点登录服务器校验用户名、密码并将登录信息设置到上下文会话中。
7、单点登录服务器重定向到A系统的/login链接,此时链接带有code和state参数。
8、A系统再次接收到/login请求,此请求携带state和code参数,系统A通过OAuth2RestTemplate请求单点登录服务端/oauth/token接口获取token。
9、A系统获取到token后,首先会对token进行解析,并使用配置的公钥对token进行校验(非对称加密),如果校验通过,则将token设置到上下文,下次访问请求时直接从上下文中获取。
10、A系统处理完上下问会话之后重定向到登录前请求的受保护资源链接。
1、用户通过浏览器访问B系统被保护的资源链接
2、B系统判断当前会话是否登录,如果没有登录则跳转到B系统登录地址/login
3、B系统首次接收到/login请求时没有state和code参数,此时B系统拼接系统配置的单点登录服务器授权url,并重定向至授权链接。
4、单点登录服务器判断此会话是否登录,因上面访问A系统时登陆过,所以此时不会再返回登录界面。
5、单点登录服务器重定向到B系统的/login链接,此时链接带有code和state参数。
6、B系统再次接收到/login请求,此请求携带state和code参数,系统B通过OAuth2RestTemplate请求单点登录服务端/oauth/token接口获取token。
7、B系统获取到token后,首先会对token进行解析,并使用配置的公钥对token进行校验(非对称加密),如果校验通过,则将token设置到上下文,下次访问请求时直接从上下文中获取。
8、B系统处理完上下问会话之后重定向到登录前请求的受保护资源链接。
loginProcessingUrl(“/login/doLogin”)//表单提交路劲,提交后执行认证逻辑
loginProcessingUrl的作用是用来拦截前端页面对/login/doLogin这个的请求的,拦截到了就走它自己的处理流程,导致我们自己后端写的/login/doLogin这个接口有写跟没写是一样的。
**(重点)**由于未在WebSecurity配置中设置successHandler,因此默认情况下将调用SavedRequestAwareAuthenticationSuccessHandler。
ExceptionTranslationFilter在认证开始前把request缓存到session中,当认证成功后,在SavedRequestAwareAuthenticationSuccessHandler里取出缓存的request,跳转回认证前用户想访问的url
AuthenticationSuccessHandler接口(登录成功之后的处理逻辑)
SpringSecurity(二十):异常处理 https://www.cnblogs.com/wangstudyblog/p/14823512.html
http.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationExceptionEntryPoint())
图 https://blog.csdn.net/weixin_64742764/article/details/124813433
Spring Security + JWT 实现单点登录 https://blog.csdn.net/xiyang_1990/article/details/124487755 https://blog.csdn.net/CSDN_KONGlX/article/details/125486825 https://blog.csdn.net/qq_18671415/article/details/118518450 http://t.zoukankan.com/7788IT-p-10693154.html https://blog.csdn.net/pxg943055021/article/details/124752669 https://blog.csdn.net/wang121213145/article/details/124850518 https://blog.csdn.net/asd747571569/article/details/122511434 OAuth 2.0实现分布式认证授权-认证服务器配置 2 https://blog.csdn.net/u011066470/article/details/119974904 Spring Security https://blog.csdn.net/m0_64714024/article/details/125549592 OAuth2.0认证和授权原理(示例代码) https://www.136.la/tech/show-45950.html Spring Security Oauth2 常用授权方式配置详细教程(一) https://blog.csdn.net/tiancxz/article/details/108856337 史上最简单的Spring Security教程(二十六):DaoAuthenticationProvider详解 https://blog.csdn.net/liuminglei1987/article/details/108279836
认证成功后回跳
Spring Security认证成功后回跳
https://blog.csdn.net/gangsijay888/article/details/81171647/
SpringSecurity保存登录前的请求页面和跳转回登录前页面的源码分析
https://blog.csdn.net/HHoao/article/details/124559410
SpringSecurity登录后重定向到登录前访问页面策略 https://blog.csdn.net/ainizfb/article/details/123221490
基于SpringSecurity OAuth2实现单点登录——集成Github实现第三方账户登录
https://blog.csdn.net/hou_ge/article/details/120455557
There is no PasswordEncoder mapped for the id "null"的解决办法
https://www.cnblogs.com/jpfss/p/11004828.html
ajax
https://wenku.baidu.com/view/917ac6e0a900b52acfc789eb172ded630b1c988c.html
springsecurity oauth2使用jwt实现单点登录(文章目录)
https://blog.csdn.net/weixin_44837750/article/details/125767591
自定义权限路径配置
https://blog.csdn.net/weixin_50025568/article/details/123548098
测试页 备份
@Order(10) @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig3 extends WebSecurityConfigurerAdapter { @Override //SuperAdmin Admin public void configure(AuthenticationManagerBuilder auth) throws Exception{ // 使用自定义身份验证组件,指定密码加密策略 //auth.inMemoryAuthentication().withUser("admin").password("123456").roles("Admin").and().passwordEncoder(passwordEncoder()); //auth.userDetailsService(userDetailsService); auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("123456")).roles("Admin"); } @Bean public static PasswordEncoder passwordEncoder(){ // return NoOpPasswordEncoder.getInstance(); return new BCryptPasswordEncoder(); } //form表单重写 @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() //.loginPage("/login.html") //.defaultSuccessUrl("/index_defaultSuccessUrl.html") //.loginProcessingUrl("/login")//表单提交路劲,提交后执行认证逻辑 //.successForwardUrl("/index.html") //.successHandler((request, response, auth) -> { System.out.println(" doLogin"); }) // .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("application/json;charset=utf-8"); RequestCache cache = new HttpSessionRequestCache(); SavedRequest savedRequest = cache.getRequest(request, response); String url = savedRequest.getRedirectUrl(); System.out.println("getRedirectUrl: " + url); response.sendRedirect(url); } }) .failureForwardUrl("/fail.html"); // 登录失败后的路劲 // http.authorizeRequests() .antMatchers("/sso/oauth/*").permitAll()// .antMatchers("/login.html").permitAll()//登录页不需要认证 .antMatchers("/login").permitAll() .antMatchers("/**/*.js", "/**/*.css").permitAll() .anyRequest().authenticated() .and() .csrf().disable(); } @Bean @Override public AuthenticationManager authenticationManager() throws Exception { return super.authenticationManager(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。