SpringSecurity,jwt oathu sso,YeZiJie

Spring Security 中文文档 参考手册 中文版 (springcloud.cc)

一 springsecurity 

SpringSecurity框架简介

  1. 安全框架:解决系统安全问题的框架。
    1. apache shire:轻量化。易于使用(配置简单)。功能够用(可满足大部分的需求)。一些特殊的需求无法实现。
    2. springsecurity:
      1. 重。难学(配置繁琐)。功能强大。
      2. spring全家桶的一员,所以和spring项目(springboot项目)集成更加容易。
      3. springsecurity底层利用的就是spring的4大特性:springbean、spring ioc、di(控制反转,依赖注入)、aop(面向切面编程)。
  2. 认证:用户是否能登录。
  3. 授权:用户是否能执行一个动作。
  4. 权限:
    1. 前端角度:菜单是否展示、按钮能不能点击
    2. 后端角度:权限对于后台而言都是一个一个完整的URL,你去控制权限,就是去控制这些URL。

2 快速入门demo(登录成功,跳转到首页)

(1)Please sign in登录页面

  1. springsecurity默认提供的登录页面。
  2. 因为springboot项目中添加了springsecurity起步依赖(组件),所以在项目启动后springsecurity默认会拦截所有的请求(而且我没有做任务的配置),要求你登录以后才能访问你具体的地址。比如,拦截项目的访问(localhost:8080,任何页面:login.html、main.html)。
  3. 默认用户名:user,密码:Using generated security passowrd
  4. 登录报404、返回报403,后面讲。
  5. 登录后,输入你想访问的rul即可。

(2)UserDetailsService详解

  1. 前因
    1. 只引入springsecurity的起步依赖包,不做任务配置的情况下。springsecurity会自动拦截所有的请求,要求使用它的用户名(admin)密码(随机,控制台打印)去登入。
    2. 因此我们不可能使用springsecurity,给我们提供的用户名和密码,我们需要使用的是数据库中的用户名和密码。
  2. 功能“集合”:自定义登录(认证)逻辑
  3. 神的冰箱:
    1. UserDetailsService.loadUserByUsername()接口
    2. 默认实现类1:JdbcUserDetailsManager:用jdbc去实现
    3. 默认实现类2:UserDetailsManager,专门的一个管理器。
    4. 默认实现类3:InMemoryUserDetailsManager,基于内存的,即可以通过配置把自定义的用户名和密码放到内存里面。应用场景:在测试阶段使用,在真正做开发的时候很少用到。
    5. 抛出的异常:UsernameNotFoundException extends AuthenticationException(认证异常) 
    6. 返回值:UserDetails接口
    7. 返回值实现类:User类(UserDetails的实现)
      1. 注意:在使用springsecurity以后,要注意项目中关于User实体类的定义了。
  4. 工作原理:自定义登录(认证)逻辑
    1. 第一步:自定义UserDetailsService实现类
    2. 第二步:传用户名,调用UserDetailsService.loadUserByUsername(String userName)
    3. 第三步:底层去数据库查询
      1. 第1步:如果用户名为空或找不到用户,抛出异常UsernameNotFoundException
      2. 第2步:用户名存在为前提,如果密码为空或不一致(是否一致的比较是在UserDetailsService.loadUserByUsername(String userName中进行的),也会抛出异常。
      3. 注意:数据库中的密码要做加密处理
    4. 第四步:UserDetailsService.loadUserByUsername()返回UserDetails对象

(3)PasswordEncoder 密码解析器详解 

  1. 前因
    1. 前端密码:前端给传过来的登录密码是明文的。
    2. 密码加密:用户注册时,把加好密的密码存入数据库。
  2. 功能“集合”:
    1. 功能1:加密密码
    2. 功能2:解密密码
  3. “神的”冰箱:
    1. PasswordEncoder(接口) 密码解析器
    2. 建议使用的实现在类1:BCryptPasswordEncoder:基于哈希算法的加密(单向)实现类。
  4. 演示:
    1. // 创建解析器
      PasswordEncoder pw = new BCryptPasswordEncoder ();
      // 对密码加密
      String encode = pw . encode ( "123" );
      System . out . println ( encode );
      // 判断原字符和加密后内容是否匹配
      boolean matches = pw . matches ( "1234" , encode );
      System . out . println ( "===================" + matches );

3 认证:http.formLogin()  

(1)自定义登录逻辑

  1. 第一步:在Spring容器中注入PasswordEncoder
  2. 第二步:实现UserDetailsService.loadUserByUsername()接口
    1. 第1步:根据username到数据库查询
    2. 第2步:根据查询到的对象比较密码
    3. 第3步:返回UserDetails对象
      1. return new User(username,password, AuthorityUtils.
                commaSeparatedStringToAuthorityList("admin,normal"));,给我们的用户准备了2个权限,一个是admin,一个是normal。
  3. 第三步:验证
    1. 第1步:重启项目
      1. 现象1:控制台没有自动生成随机密码了。
    2. 第2步:成功进入404页面
      1. 注意:404页面是因为我们没有做映射关系,localhost:8080到lmain.html的跳转。

(2)自定义登录页面

  1. 前端页面
    1. method(请求方式)必须为post
    2. 用户名(name)必须为username
    3. 密码(name)必须为password
    4. 因为在进行登录之前呢,springsecurity会有一个过滤器链(拦截器链)被执行。
  2. java编码
    1. 第一步:配置类继承WebSecurityConfigurerAdapter
      1. 注意:WebSecurityConfigurerAdapter是springsecurity中最重要的一个类,因为我们所有的配置(配置自定义登录页面、定义登录成功 失败 页面、自定义登录成功 失败 Handler)都是要以继承这个类为前提。
    2. 第二步:重写configure方法,配置自定义登录页面
    3. 第三步:重启项目
    4. 第四步:验证
      1. 第1步:localhost:8080,自定义的用户名密码,404(正确的)
      2. 第2步:localhost:8080/login.html,可以访问
    5. 第五步:问题:localhost:8080/main.html,也可以直接访问,一点拦截都没有。一般来说,登录页面是可以放行的,但其它页面(如main.html),只能是经过login.html登录或注册后才能到达的。
    6. 第六步:解决方案:授权配置,所有请求都需要被认证(先登录(页面))。
    7. 第七步:重启项目
    8. 第八步:验证时,又有问题:localhost:8080/login.html进入死循环
    9. 第九步:解决方案:放行(不拦截)以下页面:"/login.html","/login","/error.html"
    10. 第十步::重启项目
    11. 第十一步:验证时,又又有问题:localhost:8080/login.html点击登录以后,没有跳转到main.html。通过System.out.println打印可以看出,根本没有执行我们的自定义登录逻辑:UserDetailsService.loadUserByUsername(String userName)。
    12. 第十二步:解决方案:
      1. 第a步:配置自己登录逻辑
      2. 第b步:配置csrf
        1. 注意:可以简单地把csrf理解为一个防火墙。
    13. 第十三步:验证,又又又有问题,login.html登录成功以后,没有做跳转(main.html),直接报404错误。 
    14. 第十四步:解决方案:配置登录成功后跳转的页面。
    15. 第十五步:验证,又又又又有问题,这加报405
    16. 第十六步:解决方案: 
      1. 第1步:自定义XxxController.java类post请求对应的post方法
      2. 第2步:在配置中定,代表团//登录成功后跳转页面,此POST请求地址
  3. 注意:自定义的XxxController中的"/login"和页面中的“/login”没有半毛钱关系。当登录时会走配置类中的configure()方法,然后是loadUserByUsername(),而不走自定义的XxxController中的"/login"对应的方法。因为请求被springsecurity拦截后,底层做了一些处理。

(3)登录失败页面跳转

(4)自定义登录参数

(5)自定义登录成功处理器

  1. 我们之前说登录成功要跳转页面的话,要通过我们的XxxController类去实现,因为它要求使用post的方式去跳转。
        因为以后我们接触的大部分项目都是前后端分享的项目,页面跳转的控制是由前端去控制的,后端顶多就返回一个json数据给到前端。而且,我们说过了,请求必须是post请求。
        需求:如果我们就想用get请求(如重定向)呢?
        解决方案:自定义登录成功处理器。
                          因为有onAuthenti cationSuccess (HttpSe rv le tRequest request,),HttpServletResponse res ponse,Authentication authentication),所以第1个好处是:可以使用重定向(比如重定向到http://www.baidu.com)。第2个好处是:如果我们写的是一个前后端分离的话,我们的页面跳转是靠我们的前端去控制的。这时,我们完全可以通过response返回数据(比如最常见的json数据)。第3个好处是:还可以通过Authentication获取当前用户的认证信息(用户名、密码、凭证信息等)。

(6)自定义登录失败处理器

3 授权/权限/角色:authorizeRequests()、exceptionHandling()、access自定义方法、注解方式

(1)授权类型

  1. url授权(访问控制)
  2. 角色授权(访问控制)
  3. 其它授权(访问控制)

(2)配置授权api

  1. http.authorizeRequests()
    1. http.authorizeRequests() 也支持连缀写法,即点点点,一直点下去。

(3)授权公式

  1. url 匹配规则 . 权限控制方法
    1. url匹配规则
      1. anyRequest().authenticated():匹配所有(任何)请求。一般放在最后,而且要加上.authenticated()表明认证之后才能访问。为什么要放在最后呢?因为如果放在前面,所有请求都要被认证,放行(antMatchers)的那些代码就不起效果了。
      2. .antMatchers():url匹配规则,参数是不定向参数,每个参数是一个 ant 表达式,用于匹配 URL规则。2个参数的方法,还可以限定请求方式(get、post等)。
        规则如下:
               ? : 匹配一个字符
               * :匹配 0 个或多个字符
               ** :匹配 0 个或多个目录
        案例:
               .antMatchers("/js/**","/css/**").permitAll():匹配静态资源。第1个"/js/**",匹配js目录下面的所有文件和目录。同理,"/css/**"。
               .antMatchers("/**/*.js").permitAll():
        还有一种配置方式是只要是 .js 文件都放行       
      3. .regexMatchers():使用正则表达式进行匹配。与.antMatchers()的唯一区别仅仅在于参数不同。 .regexMatchers( ".+[.]js").permitAll():演示所有以.js 结尾的文件都被放行。 注意:2个参数的方法,还可以限定请求(get、post等)。
      4. .mvcMatchers():mvcMatchers()适用于配置了 servletPath (http://localhost:8080/xxxx/1.png,表明在yml或properties文件中配置了servletPath(应用名称), 即spring.mvc.servlet.path=/yjxxt )的情况。案例:mvcMatchers("/image/**") . servletPath("/xxxx") .permitAll(),其中的"/xxxx"就是应用名称。注意:很少用,因为复杂。使用antMatchers()和 regexMatchers()也能达到相同的效果,只需要在资源前面加入xxx(应用名称)即可。
      5. 建议:使用最简单最容易懂的antMatchers()。

    2. 权限控制方法(具体的访问控制):内置访问控制方法
      1. permitAll():放行所有。
      2. authenticated():必须要认证后才能访问,认证不成功就跳转到登录页面。
      3. anonymous():匿名访问。
      4. denyAll():拒绝所有。
      5. rememberMe():记住我,可能是3天,可能是5天。
      6.  fullyAuthenticated():完整的认证。即记住我的方式也要通过用户名和密码认证通过后,才能访问的资源。
    3. 权限控制方法(具体的访问控制):根据权限判断。权限名称严格区分大小写。设置权限的地方是,UserServiceImpl.loadUserByUsername()方法中的:return new User(username,password, AuthorityUtils. commaSeparatedStringToAuthorityList("admin,normal"));
      1. hasAuthority(String):匹配1个权限
      2. hasAnyAuthority(String ...):匹配多个权限中的1个即可
    4. 权限控制方法(具体的访问控制):根据角色判断。角色名称严格区分大小写。设置角色的地方是,UserServiceImpl.loadUserByUsername()方法中的:return new User(username,password, AuthorityUtils. commaSeparatedStringToAuthorityList("ROLE_abc,ROLE_def"));注意:必须是ROLE_开头。而且角色是ROLE_后面的xxx,在判断时springsecurity会自动加上前缀ROLE_。
      1. hasRole(String):匹配1个角色,如上面的abc角色。
      2. hasAnyRole(String ...):匹配多个角色的1个,如上面的abc或def角色。
    5. 权限控制方法(具体的访问控制):根据其它(如IP地址)判断。
      1. hasIpAddress(String):匹配ip地址。应用场景:系统只允许那几个管理员PC所在的IP地址才能访问。

(4)自定义403:http.exceptionHandling()

  1. 场景
    1. 出现403错误页面
  2. 原因
    1. 权限不够
  3. 解决方案
    1. 方案1:对于普通的web项目,我们可以转发或重定向到更友好的页面,显示给用户看。
    2. 方案2:对于前后端分离的项目中,可以返回json数据给到前端,前端自己给出相应的错误提示。
  4. 详细步骤:
    1. 第一步:自定义MyAccessDeniedHandler implements AccessDeniedHandler
      1. 第1步:实现handle(HttpServletRequest request, HttpServletResponse
        response, AccessDeniedException accessDeniedException) 方法
      2. 第2步:把MyAccessDeniedHandler 注入到spring容器中。
    2. 第二步:在配置类中使用http.exceptionHandling()处理

(5)基于表达式的访问控制:access自定义方法

  1. 基于access表达式的访问控制:
    1. 规则
      1. 所有的权限访问控制方法(包括了:内置访问控制方法、根据权限判断、根据角色判断、根据其它(如IP地址)判断)的底层,都是基于access表达式。
      2. access表达式和之前使用的,内置访问控制方法、根据权限判断、根据角色判断、根据其它(如IP地址)判断的授权方式是一样的,没有特别大的一个区别,甚至可以说是没区别。
    2. 使用案例:
  2. 自定义判断逻辑
    1. 原因:
      1. 内置访问控制方法、根据权限判断、根据角色判断、根据其它(如IP地址)判断的授权方式是固定好的规则,如果想自定义判断逻辑以满足特殊情况下的需求,就需要有access了。
    2. 案例:
      1. 判断当前登录的用户是否具有访问当前url的权限。如果有权限,则可以访问。如果没有权限,报出403错误。
    3. 实现步骤
      1. 怎么才能让当前用户具有某个权限呢?:
        @Service
        public class UserServiceImpl implements UserDetailsService {
        
            @Autowired
            private PasswordEncoder passwordEncoder;
            
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                if(StringUtils.isEmpty(username) || !(username.equals("admin"))){
                    System.out.println("用户不存在!");
                    throw  new UsernameNotFoundException("用户记录不存在!");
                }
        
               // 到数据库查询用户记录
        
                String password = passwordEncoder.encode("123");
               //  给当前登录的用户设置:admin、normal权限
               //  给当前登录的用户设置:QQ、AA两个角色
                return new User(username,password, AuthorityUtils.
                        commaSeparatedStringToAuthorityList("admin,normal,ROLE_QQ,ROLE_AA"));
            }
        }
      2. 第二步:编写接口:
        package com.yjxxt.springsecuritydemo.service;
        import org.springframework.security.core.Authentication;
        import javax.servlet.http.HttpServletRequest;
        public interface MyService {
           /*  描述:自定义方法
            *  作用:判断当前登录的用户是否具有权限
            *  参数:
            *      参数1:HttpServletRequest request。用于获取当前url。
            *      参数2:Authentication authentication:用于获取当前登录的用户
            *  返回:布尔值
            */
           boolean hasPermission(HttpServletRequest request, Authentication authentication);
        }
      3. 第三步:编写接口实现类:

        /**
        *
        * @since 1.0.0
        */
        @Component
        public class MyServiceImpl implements MyService {
        @Override
        public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
           Object obj = authentication.getPrincipal();
           if (obj instanceof UserDetails){
              UserDetails userDetails = (UserDetails) obj;
              Collection<? extends GrantedAuthority> authorities =userDetails.getAuthorities();
              return authorities.contains(newSimpleGrantedAuthority(request.getRequestURI()));
           }
           return false;
         }
        }
      4. 第四步:修改配置类:

        //url拦截
        http.authorizeRequests()
        //login.html不需要被认证
        // .antMatchers("/login.html").permitAll()
        .antMatchers("/login.html").access("permitAll")
        // .antMatchers("/main.html").hasRole("abc")
        .antMatchers("/main.html").access("hasRole('abc')")
        .anyRequest().access("@myServiceImpl.hasPermission(request,authentication)
        ")

(6)基于注解的访问控制:一共5个注解,常用的就是2个(@Secured、@PreAuthorize/@PostAuthorize) 

  1. 原因
    1. 之前我们对url访问控制权限的配置都是通过配置类来完成的,但是在springsecurity也提供了许多访问控制权限相关的注解供大家使用。
    2. 可以提高开发效率,代码更加简洁。
  2. 注解的格式
    1. 这些注解可以写到 Service 接口或方法上,
    2. 也可以写到 Controller或 Controller 的方法上。
    3. 通常情况下都是写在Controller的方法上,控制接口URL是否允许被访问。
  3. 常用注解
    1. @Secured:
      1. 专门判断是否具有角色的。能写在方法或类上。参数要以 ROLE_开头。
      2. 等价于:内置方法hasRole()。
    2. @PreAuthorize/@PostAuthorize
      1. 相同点:
        1. @PreAuthorize 和@PostAuthorize 都是方法或类级别注解。
        2. @PreAuthorize 和@PostAuthorize 都是用来判断权限的。
        3. 等价于:内置方法hasAuthority()
      2. 区别:
        1. @PreAuthorize 表示访问方法或类在执行之前先判断权限,大多情况下都是使用这个注解,注解的参数和access()方法参数取值相同,都是权限表达式。
        2. @PostAuthorize 表示方法或类执行结束后判断权限,此注解很少被使用到
  4. 注意事项
    1. 这些注解默认是不能使用的,需要通过在启动类顶部加上@EnableGlobalMethodSecurity 进行开启后使用。
    2. 如果设置的条件允许,程序正常执行。如果不允许会报 500。
      1. 报500的工作原理:
        1. 第一步:用户登录
        2. 第二步:条件判断
          1. 第1次进来,发现条件不符合,就会判断有没有登录。
            1. 如果已经登录过了,报500
            2. 如果没有登录,那需要登录以后,再次进行条件判断。
              1. 如果符合条件,可访问。
              2. 如果条件不符合,报500

4 其它

(1)RememberMe功能实现:http.rememberMe()

  1. 应用场景
    1. 在前端页面记住我的对话框中打勾,可以记住3天 或者 5天 或者 1个礼拜。
    2. 3天 或者 5天 或者 1个礼拜,可以设置。
    3. 下次登录的时候,不需要输入用户名和密码,直接就登录成功了。
  2. springsecurity RememberMe的工作原理
    1. 第一步:Spring Security Remember Me 记住我 功能,用户只需要在登录时添加 remember-me复选框,
    2. 第二步:取值为 true
    3. 第三步:Spring Security 会自动把用户信息存储到数据源中( 建议使用数据库 ,测试时可以把数据存储到内存中),
    4. 第四步:以后就可以不登录进行访问
  3. 详细步骤
    1. 第一步:添加依赖
      1. mybatis-spring-boot-starter、mysql-connector-java
    2. 第二步:配置文件
      spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
      spring.datasource.url= jdbc:mysql://localhost:3306/security?
      useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
      spring.datasource.username= root
      spring.datasource.password= root
    3. 第三步:编码
      1. 第1步:配置类
        1. 第a步:http.rememberMe().userDetailsService(userService).tokenRepository(persistentTokenRepository);
          1. 其中userService,是我们的自定义登录逻辑类的实例,可从spring容器中获取。
          2. 其中persistentTokenRepository,是持久层对象类的实例,需要新建。
      2. 第2步:新建持久层对象类
        @Bean
        public PersistentTokenRepository getPersistentTokenRepository(){
               JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
               jdbcTokenRepository.setDataSource(dataSource);
                //自动建表,第一次启动时需要,第二次启动时注释掉(不然报错)
               jdbcTokenRepository.setCreateTableOnStartup(true);
               return jdbcTokenRepository;
        }
      3. 第3步:重启项目
        1. 第a步:数据库自动创建了相应的表
    4. 第四步:前端,加入记住我对话框
      1. 第1步:<input type="checkbox" name="remember-me" value="true"/><br/> ,这里的name必须为remember-me。
    5. 第五步:验证
      1. 第1步: 重启项目(注释掉)
      2. 第2步:勾选记住我,点击登录 ,跳转到main.html页面
      3. 第3步:关掉浏览器
      4. 第4步:重新打开浏览器,直接在地址栏中写入,localhost:8080/main.html可以直接进,不需要登录了
      5. 第5步:不可以到数据库中查看数据
  4. 其它
    1. 记住我默认可记住2周。可以改, . tokenValiditySeconds ( 120 )。
    2. 自定义参数(即可改前端的 name="remember-me"):.rememberMeParameter()。
    3. 自定义记住我的实现:rememberMeService()。

(2)Thymeleaf中SpringSecurity的使用

  1. 应用场景
    1. 主要应用在非前后端分离的项目中,在jsp或Thymeleaf中SpringSecurity的使用。
    2. 注:而对于前后端分离的项目,权限的控制一般都是由前端开发人员来控制的,不会用到springsecurity。
  2. 详细使用步骤:
    1. 第一步:pom.xml加入依赖。这样我们才能在Thymeleaf中使用SpringSecurity
    2. 第二步:前端。如何在Thymeleaf中使用SpringSecurity?
      1. 第1步:在 html 页面中引入 thymeleaf 命名空间和 security 命名空间
      2. 第2步:在thymeleaf中使用SpringSecurity
        1. 获取属性:比如,可以获取当前登录用户的信息(用户名、密码、权限等)
        2. 权限判断:比如,可以根据当前登录用户的权限来控制按钮的显示与隐藏。
          1. 其实就是我们的access表达式。

(3)退出登录:http.logout()(Thymeleaf中SpringSecurity的使用)

  1. 详细步骤
    1. 第一步:前端
      1. 第1步:加入“退出登录”标签。就这么整完了,就这么快。
    2. 第二步:验证
      1. 第1步:重启
      2. 第2步:点击“退出登录”,返回“登录页面”,但地址栏url地址后面多了“?logout”
  2. 退出登录可配置:http.logout()
    1. logoutUrl():退出登录url。
    2. logoutSuccessUrl():退出登录成功跳转的页面。
    3. addLogoutHandler(LogoutHandler):退出登录处理器。
    4. clearAuthentication(boolean):是否清除认证状态,默认为 true。
    5. invalidateHttpSession(boolean):是否销毁 HttpSession 对象,默认为 true。
    6. logoutSuccessHandler(LogoutSuccessHandler):退出成功处理器。
  3. 注意项目:
    1. 一般情况下,我们做“退出登录”的话,使用Thymeleaf+SpringSecurity默认的使用方式即可。但如果想变量,可以变更。
    2. 一般情况下,我们最多使用到logoutUrl()、logoutSuccessUrl()就可以了,因为SpringSecurity底层已经为我们做了很多很多工作了。

(4)SpringSecurity中的CSRF:http.csrf().disable()(Thymeleaf中SpringSecurity的使用)

  1. 前面:简单把CSRF理解为一个防火墙。
  2. 什么是CSRF?
    1. 跨站(跨域)请求伪造。
      1. 跨域: 只要网络协议、ip 地址、端口中任何一个不相同就是跨域请求。
      2. cookie: 客户端与服务进行交互时,由于 http 协议本身是无状态协议,所以引入了cookie进行记录客 户端身份。在cookie中会存放session id用来识别客户端身份的。在跨域的情况下,session id 可能被第三方恶意劫持,通过这个 session id 向服务端发起请求时,服务端会认为这个请求是 合法的,可能发生很多意想不到的事情。
      3. 防护:从 Spring Security4开始CSRF防护默认开启。默认会拦截请求。进行CSRF处理。CSRF为了保 证不是其他第三方网站访问,要求访问时携带参数名为 _csrf 值为token(token 在服务端产生) 的内容,如果token和服务端的token匹配成功,则正常访问。
  3. CSRF的工作原理
    1. 第一步:你第1次登录的时候,会颁发一个csrf的token给你的客户端浏览器。
    2. 第二步:客户端浏览器以后的每次请求都要携带这个token才得。
      1. 如果客户端浏览器给的token为空或不正确(即使sessionId一样),就会被认为此次访问是一次非法访问。
    3. 总结:也就是除了验证sessionId以外,还额外要验证token,多加了一层验证。
  4. 前端展示CSRF
    1. 非常简单<input type = "hidden" th:value = "${_csrf.token}" name = "_csrf" th:if = "${_csrf}" />
  5. 为什么要关CSRF?
  6. 实际项目中要不要关闭CSRF?

二 oathu2协议

1 简介

(1)业务

  1. 因为要实现跨系统跨语言的第三方认证(第三方登录),各系统之间要遵循一定的接口协议。
    1. 有很多网站都有第三方登录,比如都去接入并登录微信、QQ、新浪、百度等。那网站去做第三方登录时,就要求第三方做认证(即第三方认证)。网站在做第三方认证的时候,就要去第三方获取用户资源(比如用户名、密码)。
            问题是,网站和第三方系统可能使用不同的技术,甚至不同的语言(java、c、c++、php)去实现。而不同的语言之间,它们的认证协议可能有所不同,就很难做到每个语言的认证协议都是统一。你比如说,网站第三方登录的是微信,那么不可能让微信针对每种语言都写一套认证协议,太麻烦了。
           这时就需要有一个通用的标准,每种语言都遵循这种标准进行认证。这样就屏蔽了,不同系统的不同语言之间认证的差异。

(2)需求

  1. 第三方认证技术方案最主要是解决认证协议的通用标准问题。

(3)思路

  1. oathu2只是一个协议,一个通用标准,第三方认证的通用标准。
  2. 标准是什么?就是秦国在统一六国之前,每个国家都有自己的货币。那么国与国之间进行交易就比较麻烦(那时,会以物换物)。而在秦国统一六国之后,大家都用统一的货币,交易起来就很方便了。
  3. 这个标准是什么呢?OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。
  4. 任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务。
  5. 而具体的实现都要求各个语言自己去实现。

(4)原理

  1. 用户资源:简单来说就是用户名和密码。
  2. 用户资源的授权:比如网站需要微信的用户资源(用户名和密码),微信不会直接给到网站。怎么样才能让微信把用户资源给到网站呢?因为微信上保存的用户资源本来就只是属于用户本人所有的,因此这就要用户去授权、去确认(如扫码登录微信,并点击“授权”按钮),微信才会把用户资源发送给网站。

(5)工作流程

  1. 第一步:用户来到网站的登录页面,快速登录栏有:微信、QQ、新浪、百度。
  2. 第二步:用户点击微信图标(不输入用户名和密码)。
  3. 第三步:网站向微信发送第三方认证。
  4. 第四步:微信发送授权页面给用户,让用户确认是否把用户资源信息发送给网站,比如微信扫码登录。
  5. 第五步:用户跟微信说确认授权(点击授权按钮)。
  6. 第六步:微信授权服务器会把一个授权码给到网站。
  7. 第七步:网站根据授权码去微信认证服务器去申请令牌。
  8. 第八步:如果授权码有效,微信会返回令牌给网站。
  9. 第九步:网站拿着令牌去微信用户服务器拿用户的信息。
    1. 注意:一般第三方的认证服务器和用户资源服务器是分开的。
  10. 第十步:微信用户服务器校验令牌的合法性。
  11. 第十一步:如果令牌合法,就把用户信息返回给(响应)网站。
  12. 第十二步:微信响应完成后,与微信相关的操作就没有了,剩下呢,都是网站自己内部的操作。比如,拿着微信响应的用户资源去数据库查询验证并登录。

 2 授权模式

(1)授权码模式,最常用,最重要(Authorization Code)

  1. Client:我们的客户端,是我们自己开发的应用。
  2. User-Agent:用户代理。比如,别人要通过浏览器访问我们的应用,其中的浏览器就是用户代理。
  3. Resource Owner:资源拥有者。就是用户本身
  4. Authorization Server:授权服务器
  5. Client Identifier:客户(端)凭证
  6. Redirection URI:重定向的URI
  7. User authenticates:用户授权
  8. Authorization Code:授权码
  9. Authorization Token:访问令牌
  10. Optional Refresh Token:刷新令牌

  1. 第一步:A:Client和User-Agent关联上
  2. 第二步:用户点击了微信登录。
  3. 第三步:A1:User-Agent携带Client Identifier和Redirection URI去找Authorization Server
  4. 第四步:B1:Authorization Server要求User authenticates
  5. 第五步:B:用户授权完成
  6. 第六步:B1:User-Agent告诉Authorization Server用户已经授权了
  7. 第七步:C1:Authorization Server返回一个Authorization Code给到User-Agent
  8. 第八步:C:Client拿到Authorization Code
  9. 第九步:D:Client根据Authorization Code和Redirection URI去请求Authorization Server
  10. 第十步:E:Authorization Server返回一个Authorization Token或Optional Refresh Token给Client
  11. 第十一步:有了Authorization Token就可以去访问“资源服务器(没画出来)”获取用户资源。
  12. 第十二步:只剩下User-Agent本身的操作了。

  1. 场景类比:买电影票看电影。即使用电子凭据去领取真实的电影票,才能进去看电影。

(2)简化授权模式,很少用,加2步就可以用授权码模式了(Implicit)

  1. Web-Hosted Client Resource:客户端源码
  2. Access Token In Fragment:访问令牌。

  1. 第一步:A1:User-Agent携带Client Identifier和Redirection URI去找Authorization Server
  2. 第二步:B1:Authorization Server要求User authenticates
  3. 第三步:B:用户授权完成
  4. 第四步:C1:Authorization Server直接把Redirection URI和Access Token In Fragment返回给User-Agen。
    1. 注意:这里简化了,没有授权码的事情了。简化的就是授权码的获取,以及根据授权码去获取令牌。
    2. 注意:这次的令牌给在Redirection URI后面,我们需要手动获取。
  5. 第五步:D:User-Agent把Redirection URI和Access Token In Fragment发送到Web-Hosted Client Resource
  6. 第六步:E:令牌返回给User-Agent
  7. 第七步:G:Client获取令牌
  8. 第八步:有了Authorization Token就可以去访问“资源服务器(没画出来)”获取用户资源。
  9. 第九步:只剩下User-Agent本身的操作了。

(3)密码模式,偶尔用(Resource Owner PasswordCredentials)

  1. 第一步:密码模式:用户直接在我们的网站上输入第三方的用户名和密码。
  2. 第二步:我们带着用户输入的第三方用户名和密码去找第三方认证服务器(授权服务器),进行认证。认证成功,认证服务器(授权服务器)直接给令牌。
  3. 第三步:根据令牌获取用户资源

  1. 应用场景:
    1. 公司开发了一套应用,一个app版的,一个是网站版的。其中,app版和网站版使用的是同一个数据库。现在网站版的应用想要获取app版应用中的用户资源,因为使用的是同一个数据库、授权服务器、资源服务器,所以直接返回令牌获取用户资源即可。
    2. 比如,阿里巴巴的淘宝、天猫、支付宝。可以用支付宝账户去登录淘宝和天猫。

(4)客户端模式,最简单,很少用(Client Credentials)

  1. 第一步:A:client授权
  2. 第二步:B:Authorization Server给令牌

  1. 应用场景:
    1. 一般都是用在设备上面,一些软件也在用。
    2. 比如,docker。docker要去拉取镜像之前,也要获取授权。获取授权之后,才会给你拉取镜像。这个时候docker就会主动去找服务器,要求授权,然后服务器就会给docker一个令牌,最后docker就可以完整地去拉取镜像了。

(5)刷新令牌

  1. 第一步:A:client拿着授权码去找Authorization Server
  2. 第二步:B:Authorization Server返回Refresh Token
    1. 为什么要有Refresh Token呢?因为Access Token(访问令牌)是有过期时间的。过期时间可以设置。
  3. 第三步:G:通过Refresh Token找Authorization Server
  4. 第四步:H:Authorization Server颁发新的Access Token和Refresh Token。
    1. 这样省去了授权码模式下,关于使用授权码获取令牌的复杂步骤
  5. 第五步:使用Access Token获取资源服务器的用户资源

  1. 类比场景:电影票过期了,还没进去看,服务员给你换到下一场(同一部影片)。

三 springsecurity oathu2框架(springsecurity实现oathu2,即java层配合springsecurity框架搞出来的一个oathu2的具体实现)

1 授权服务器

  1. 注:括号中写的就是到时候我们要去调用的接口,只是到时候调用时没有“2”字。
    1. /oauth/authorize:调用授权
    2. /oauth/token:调用令牌

2 Spring Security Oauth2架构

体系组织:如上图所示
  1. springsecurity oathu2框架不仅仅包含springsecurity oathu框架,里面还带有springsecurity框架,还有用户自己实现的一些代码。
    1. spring security框架:橙色
    2. springsecurity oathu框架:黄色
    3. Implemented by Deveplper:用户自己实现的代码

工作流程1-me:

  1. (1)
    1. 第一步:User通过User agent去访问,此时Client和User agent都没有token。
    2. 第二步:请求到达Client的OAuth2RestTemplate,因为没有token而报错。
    3. 第三步:Client的OAuth2ClientContextFilter拦截这个报错。
  2. (3)
    1. 第一步:拦截这个报错后Client重定向到Authorization server。
  3. (2)
    1. 第一步:经过授权端点Authorization Endpoint进行授权。
    2. 第二步:授权端点Authorization Endpoint会使用授权服务AuthorizationServerTokenServices服务生成授权码。
  4. (3)
    1. 第一步:授权码返回给Client
    2. 第二步:Client拿到授权码后再次请求Authorization server,这次请求的是令牌端点TokenEnpoint
  5. (2)
    1. 第一步:令牌端点TokenEnpoint拿着授权码去找AuthorizationServerTokenServices服务,验证授权码。如果授权码正确,就颁发令牌给
  6. (3)
    1. 第一步:令牌返回给Client。
  7. (4)
    1. 第一步:Client携带令牌去找资源服务器Resouce server
    2. 第二步:资源服务器Resouce server的认证管理器OAuth2AuthenticationManager
    3. 第三步:认证管理器OAuth2AuthenticationManager调用ResourceServerTokenServices服务进行令牌的校验。
      1. 如果校验通过则,把用户资源返回给Client。
工作流程2:
  1. 用户访问,此时没有Token。Oauth2RestTemplate会报错,这个报错信息会被Oauth2ClientContextFilter捕获并重定向到认证服务器
  2. 认证服务器通过Authorization Endpoint进行授权,并通过AuthorizationServerTokenServices生成授权码并返回给客户端
  3. 客户端拿到授权码去认证服务器通过Token Endpoint调用 AuthorizationServerTokenServices生成Token并返回给客户端
  4. 客户端拿到Token去资源服务器访问资源,一般会通过Oauth2AuthenticationManager调用ResourceServerTokenServices进行校验。校验通过可以获取资源。

3 Spring Security Oauth2授权码模式

  1. 第一步:创建maven、springboot、spring web、Spring Security项目
  2. 第二步:pom.xm
    1. 剩下的依赖去文档中拷贝,因为我们要用springcloud的方式来引入springsecurity oathu2。为什么要这样做呢?因为springboot的springsecurity oathu2有点问题,虽然它支持资源服务器的配置,而授权服务器的配置太麻烦了,所以换成简单一点的方式。
    2. springcloud的版本号:<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    3. springcloud的依赖:<artifactId>spring-cloud-dependencies</artifactId>,专门用来引入springcloud
  3. 第三步:application.properties
  4. 第四步:编码 - 配置springSecurity框架 - 并配置自定义登录逻辑
    1. 第1步:自定义实体类
      1. 注意:正常开发过程中,用户名、密码、权限都是要去数据库查询出来的。
    2. 第2步:自定义登录逻辑:UserDetailsService.loadUserByUsername()
      1. 第a步:返回上面的new User,并配置角色和权限。
    3. 第3步:编写 - 配置springSecurity框架
      1. 第a步:注入密码加密工具bean。
      2. 第b步:关闭csrf
      3. 第c步:放行授权端点、资源端点的url。
      4. 第d步:剩下的,都要求认证。
      5. 第e步:允许表单提交
      6. 注意:通过and()就可以回到http.的状态,就可以继续往下“点”。比如,案例中就可以.formLogin(),再.permitAll()放行。因此,如果想在配置类中使用多个http.的话,通过and()返回到http.状态后,就可以继续往下“点”了。
  5. 第五步:编码 - 配置Spring Security Oauth2
    1. 概述
      1. 思考一下Spring Security Oauth2有哪些地方要配置?第一个配置验证服务器;第二个配置资源服务器,比如配置资源作用域(范围)。
    2. 详细步骤
      1. 第1步:编写代码 - 配置验证服务器(授权服务器):AuthorizationServerConfifig.java
        1. 第a步:配置客户凭证(用户名admin、密码(加密)112233)。客户凭证,用来确定你这个网站,并确定你这个网站需要什么样的授权码(获取对应权限范围的令牌)。
        2. 第b步:配置用于获取授权码的重定向uri。这里不管你重定向到哪里都可以,因为重定向uri,只是为了获取授权码。
        3. 第c步:授权范围。不同的client要求的授权范围不一样,有些只要用户的用户名和密码,有些可能需要用户的图片(如微信头像)......
        4. 第d步:授权类型
        5. 注意:正常开发过程中,上面的很多信息都是要去数据库查询出来的。
      2. 第3步:准备资源
        1. 概述:
          1. 即用户信息,这里返回当前登录用户的信息:Authentication authentication
        2. 详细步骤:
          1. 第a步:为了方便,这里使用的是一个XxxController.java,使用Authentication返回当前登录的用户即可。
      3. 第2步:编写代码 - 配置资源服务器:ResourceServerConfig.java
        1. .anyRequest().authenticated():所有的请求都需要被授权服务器进行授权(认证)
        2. and():回到http.
        3. .requestMatchers().antMatchers("/user/**"):当你有令牌的时候,就放行类似"/user/**"的请求。
  6. 第六步:验证
    1. 第1步:启动项目
    2. 第2步:验证:获取授权码
      1. 授权端点:
        http://localhost:8080/oauth/authorize?response_type=code&client_id=admin&redirect_uri
        =http://www.baidu.com&scope=all
        1. response_type=code:表示返回的是授权码
        2. client_id=admin:客户id。在授权服务器配置中配置的
        3. redirect_uri =http://www.baidu.com:重定向uri。在授权服务器配置中配置的。
        4. scope=all:把的的作用域。在授权服务器配置中配置的。
      2. 登录
      3. 获取授权码(在重定向uri后面):thttps://www.baidu.com/?code=lFIilh
    3. 第3步:验证:根据授权码获取令牌(必须POST请求,建议使用postman发送post请求)
      1. 端点:localhost:8080/oauth/token
      2. postman如下图操作:
      3. 报错:Error: Header name must be a valid HTTP token [“授权“]
      4. "status": 401

      5. 用非汉化的postman是成功的:

        1. access_token:访问令牌;token_type:token的类型;expires_in:失效时间;scope:范围。

    4. 第3步:验证:根据token去资源服务器拿资源(可用Get请求,也可用POST请求,建议使用postman发送post请求)
      1. 地址:为XxxController.java的映射地址:localhost:8080/user/getCurrentUser
        1. 如果没传令牌,就报没有授权的错误
        2. 如果令牌不正确,就报令牌不合法的错误
      2. postman:传入令牌,获取到用户资源
  7. 注意事项:
    1. 授权码只能用一次,如果获取不成功,那么只能重新获取新的授权码。

4 Spring Security Oauth2 密码模式

  1. 密码模式非常简单,只要在授权码模式上稍做调整就可以了
    1. 总配置类的调整:
      1. 注入授权管理器:
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    2. 授权服务器配置调整:
      1. 覆盖方法:
        /**
         * 密码模式
         * @param endpoints
         * @throws Exception
         * 参数1:AuthorizationServerEndpointsConfigurer:授权服务器端点的配置
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            //  .authenticationManager(authenticationManager):授权管理器。
            //  .userDetailsService(userService):使用自定义的登录逻辑。
            endpoints.authenticationManager(authenticationManager)
                    .userDetailsService(userService);
        }
      2. 设置授权类型为密码模式:
        1. .authorizedGrantTypes("authorization_code","password");
        2. 注:这里可以配置多个模式,即可以允许它有多个模式去用
    3. 重启项目,并验证:成功获取令牌,根据令牌成功获取用户资源

5 在Redis中存储token

  1. 业务
    1. 之前我们生成的token都是直接在内存里面的,在生产环境中这样做是不合理的。因为token放在内存中的话,可能会造成token丢失,所以token理应放到数据库中或者是缓存中。那放在关系型数据库中还是放在缓存中呢?因为放在关系型数据库中可能获取的时候会比较慢,所以我们一般会把token放在缓存(如redis中)。
  2. 需求:把token放到redis中
  3. 详细步骤:
    1. 第一步:pom.xml,添加redis相关依赖
    2. 第二步:application.properties
      1. 第1步:配置redis的用户名和密码
    3. 第三步:编码 - token放入redis
      1. 第1步:编写redis配置类 - 使用redis存储token的配置 - 返回TokenStore
      2. 第2步:授权服务器的调整
        1. . tokenStore(tokenStore); :token存储的位置tokenStore,位置可以是:内存、数据库、缓存。
    4. 第四步:验证
      1. 第1步:重启项目
      2. 第2步:密码模式下获取令牌
      3. 第3步:查看redis工具:
        1. access:令牌。auth:授权。auth_to_access:授权到访问。client_id_to_access:授权到访问。

四 jwt

1 常见的认证机制

(1)HTTP Basic Auth:http基本认证

  1. 最简单的
  2. 为什么每次都要输入username和password呢?因为http是无状态的,没办法保存你的状态,所以要在每次http请求时都得携带username和passwrod。

(2)Cookie Auth:cookie认证,Servlet时就学了

  1. 第一步:在browser端使用验证码、用户名、密码进行登录。
  2. 第二步:server返回Http 200 OK响应,在服务端创建Session,同时在browser端创建cookie,并把服务端的sessionId保存到cookie中。
  3. 第三步:之后browser对server的每次请求都要携带保存有sessionId的这个cookie。
  4. 第四步:server通过cookie中的sessionId查找和序列化化session。
  5. 第五步:如果校验session成功,则返回http 200 ok。

(3)OAuth:oauth协议认证,上面刚刚讲过,所以我们应该很熟悉

  1. 无需将用户名和密码提供给第三方应用的前提是,不使用oauth的密码模式,因为如果使用的是oauth的密码模式就要提供用户名和密码。
  2. 工作流程图:
    1. 应用场景
      1. oauth协议认证比较适合个人消费者类的互联网产品,比如说社交类的app使用,如论坛、电商网站都可能有第三方认证。反之,传统的系统很少用到第三方登录(oauth协议认证)。
    2. 工作流程
      1. 第一步:客户端请求授权。
      2. 第二步:用户确认授权,授权码返回给客户端。
      3. 第三步:客户端根据授权码去找授权服务器,校验授权码。
      4. 第四步:授权服务器返回访问令牌给客户端。
      5. 第五步:客户端拿着访问令牌去找资源服务器,获取用户的被保护的用户资源。
      6. 第六步:资源服务器返回用户资源给到客户端。

(4)Token Auth:基于Token的认证。

  1. Token Auth的特点
    1. 在server端不用去存储用户的登录记录(与cookie auth相反)。
  2. 工作流程(注意与cookie auth的区别)
    1. 第一步:在browser端使用验证码、用户名、密码进行登录。
    2. 第二步:server返回Http 200 OK响应,把发送一个token给browser保存(如放在cookie 或 local Storage 或 session storage) 。
    3. 第三步:之后browser对server的每次请求都要携带token。
    4. 第四步:server校验token。
    5. 第五步:如果校验token成功,则返回http 200 ok和数据。
  3. Token Auth与cookie auth的区别是什么?
    1. 如果把token放在cookie里面,那么Token Auth与cookie auth看起来没有太多的区别。唯一的区别在哪里呢?cookie auth时会把用户的信息保存在session里面,然后去做校验。而Token Auth是不需要去存任何用户信息的,即在server端没有任何的用户信息,因此一般情况下token是无状态的。
    2. Token Auth比cookie auth更节约服务器资源,因为不需要在Server端存Session了,不再创建Session对象,所以Token Auth比cookie auth更节约服务器资源。
  4. Token Auth的优点(Token机制相对于Cookie机制又有什么好处呢?)
    1. 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息(Token)时通过HTTP请求头进行传输(ps:而不是把Token放到cookie,携带cookie进行传输,因为说过了cookie不允许跨域。而相反,把token放在http请求头中,就可以跨域了)
    2. 无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session(对象)信息,因为Token自身包含了所有登录用户的信息(ps:但也不要直接把用户名和密码放到里面不然黑客一解析就可以得到你的用户名和密码了。开发时要懂得,哪些信息是可以放到其中,哪些敏感信息不能放到其中的,把握到度),只需要在客户端的cookie或本地介质存储状态信息。(ps:相反,Cookie auth需要在服务器创建session对象,用于保存用户信息。)
    3. 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可。(ps:以前在使用oauth协议认证的时候,有专门的授权服务器。授权服务器主要做两个事情,第一个是颁发授权码,第二个是根据授权码去颁发令牌。但如果使用Token auth的话,是可以不存在授权服务器的。也因此得出,Token auth比oauth更加轻量。)
    4. 无序列表基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在于多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google,Microsoft)。

2 jwt简介

(1)什么是jwt

  1. 一个标准,和oauth2一样jwt也是一个协议一个标准。 
  2. 基于json的网络应用的一种令牌。       
  3. 自包含的协议格式?jwt token本身就包含了一些要提供给server的信息。
  4. ps:jwt比oauth2更加的轻量,因为jwt不需要有授权服务器。jwt直接是通过资源服务器颁发token、解析token、校验token。

(2)jwt的组成

  1. 概述
    1. jwt本质是就是一个字符串(ps:因为json本身也是一个字符串)。
  2. 组成
    1. 头部(header)
      1. 作用:描述关于该JWT的最基本的信息。
      2. 格式:这也可以被表示成一个JSON对象。
      3. 展示:Base64加密
      4. 注意:PS:因为Base64是对称加解密的,所以Base64加密其实非常非常不安全。什么是对称加解密呢?就是把密文重新通过Base64解密,立即可以得到原来的明文信息。
    2. 负载 或 载荷 或 荷载(Payload):用的也是Base64是对称加解密,不安全
      1. 作用:真正存放有效信息的地方。
      2. 有效信息包含三个部分
        1. 第1部分:标准中注册的声明(建议但不强制使用)
        2. 第2部分:公共声明
        3. 第3部分:私有声明
          1. ps:提供者和消费者所共同定义的声明,中为什么要“共同”呢?因为就像协议、标准一样,提供者和消费者都要知道怎么解析,哪一部分代表什么信息,这样才能正确地进行处理。
    3. 签证、签名(signature)
      1. signature非常非常重要,因为前面的头部和负载都使用Base64对称加解密,而signature是(盐,一定要保密)的,可以说signature才是jwt安全性的保障。
      2. 因为盐是安全性加密的保障,所以盐一定要保密,不能被客户端知道。
      3. 完整的签证信息
        1. 完整的签证信息=第一部分base64编码的字符串   点   第二部分base64编码的字符串    点   (第一部分64 + 第二部分64 + 盐,按照之前设置的签名算法(如alg:HS256 或alg:HMAC)进行加密得到的字符串)

3 jjwt简介

(1)什么是jjwt?

  1. jjwt是jwt标准的一种实现方式。
  2. jwt的实现方式还有很多种,甚至用java去实现jwt的方式都有很多种啦。

(2)快速入门

  1. 第一步:创建SpringBoot工程
  2. 第二步:pom.xml,引入依赖
  3. 第三步:junit 单元测试类
    1. 第1步:jwt token的创建
    2. 第2步:jwt token的验证(校验)和解析
    3. 第3步:jwt token过期校验
    4. 第4步:自定义claims

五 springsecurity oathu2整合jwt

  1. springsecurity oathu2 密码模式整合jwt
    1. 前情:
      1. 使用的项目:springsecurity oathu2 密码模式
      2. 之前我们的令牌是bearer token令牌,非常短
      3. 那我们想要整合jwt的话呢,要做一些改造
    2. 详细步骤
      1. 第一步:pom.xml
        1. 第1步:删除redis相关的依赖
      2. 第二步:application.properties
        1. 第1步:删除redis相关配置
      3. 第三步:编码
        1. 第1步:删除redis配置类:RedisConfig.java
        2. 第2步:jwt token的配置类:JwtTokenStoreConfig.java
          1. 第1步:注入(new)JwtTokenStore的bean到spring容器中。
          2. 第2步:注入access token到jwt token的转换器到spring容器中。
        3. 第3步:改造授权服务器配置类
          1. 第1步:删除redis存储token的代码
          2. 第2步:注入jwtTokenStore
          3. 第3步:注入access token到jwt token的转换器
      4. 第四步:验证
        1. 第1步:重启项目
        2. 第2步:postman发送post请求获取jwt token(令牌)
        3. 第3步:postman根据jwt token发送get请求获取用户资源
  2. 扩展JWT中存储的内容
    1. 前情
      1. 上面完成springsecurity oathu2 密码模式整合jwt。
      2. 拉下来,实现往jwt中添加自定义的内容。
      3. 注意:有区别于jjwt中使用.claim("logo","yjxxt.jpg");添加自定义内容的方式
    2. 详细步骤
      1. 第一步:创建jwt内容增强器类
        1. 第1步:添加增强信息:info.put("enhance","enhance info");
      2. 第二步:改造jwt配置类
        1. 第1步:注入jwt内容增强器类到spring容器中
      3. 第三步:改造授权服务器配置类
        1. 第1步:注入token内容增强器bean:private JwtTokenEnhancer jwtTokenEnhancer;
        2. 第2步:声明token内容增强器链,并放入token内容增强器、access token到jwt token转换器
        3. 第3步:配置token内容增强器链:.tokenEnhancer(enhancerChain);
      4. 第四步:验证
        1. 第1步:重启项目
        2. 第2步:postman获取令牌
        3. 第3步:去官网解析令牌,看到增强信息
  3. Java中解析JWT中的内容
    1. 概述
      1. 目标:springsecurity oathu2 密码模式整合jwt项目中,解析jwt token。因为springsecurity oathu2 密码模式整合jwt项目只能把access token转换为jwt token,但是并不能解析。
      2. 这个解析本质上还是得用jjwt来完成
    2. 详细步骤
      1. 第一步:pom.xml
        1. 第1步:添加jjwt的依赖
      2. 第二步:改造获取用户资源的XxxController.java类
        1. 第1步:获取到请求头
        2. 第2步:获取请求头中的jwt token
      3. 第三步:验证
        1. 第1步:重启项目
        2. 第2步:postman发送post请求获取jwt token
        3. 第3步:postman中的请求头中加入jwt token,postman发送获取用户资源的get请求。
        4. 第4步:效果:解析出很多东西。
  4. 刷新令牌
    1. 概述
      1. 为什么要有刷新令牌呢?因为令牌本身是无状态的,所以服务端是无法立即去控制令牌是否有效的,只能通过失效时间去控制。
      2. 如果令牌失效的话,要重新走一遍获取令牌的流程,很麻烦。为了简化一些步骤,快速得到新的令牌,我们直接通过刷新令牌去获取。
    2. 详细步骤
      1. 第一步:改造授权配置类
        1. 第1步:在授权类型中,加入一个"refresh_token"
      2. 第二步:验证
        1. 第1步:重启项目
        2. 第2步:postman发送post请求获取令牌,同时得到一个刷新令牌
        3. 第3步:postman根据刷新令牌获取新的令牌、新的刷新令牌
        4. 第4步:postman发送get请求成功获取用户资源
    3. 注意事项
      1. 令牌和刷新令牌都可以设置失效时间

六 sso

  1. 单点登录sso:登录了百度新闻以后,在百度贴吧、百度视频、百度地图的页面,分别刷新一下浏览器就会自动(默认)登录百度贴吧、百度视频、百度地图。
  2. 原理图:

    1. 工作流程
      1. 第0步:用户在浏览器输入用户名和密码,想登录到应用系统1
      2. 第1步:登录信息发送到第三方认证系统,校验
      3. 第2步:第三方认证系统给浏览器返回1个ticket
      4. 第3步:浏览器携带此ticket去访问应用系统2
        1. 第a步:应用系统2内部会重定向(+ticket)到第三方认证系统
      5. 第4步:第三方认证系统对ticket进行校验。
        1. 如果校验通过,就认为是已经登录过的用户,就可以直接登录,不用再重新登录了。效果是:刷新浏览器,就默认给我们登录成功。
      6. 第5步:浏览器携带此ticket去访问应用系统3
        1. 第a步:应用系统3内部会重定向(+ticket)到第三方认证系统
      7. 第6步:第三方认证系统对ticket进行校验。
        1. 如果校验通过,就认为是已经登录过的用户,就可以直接登录,不用再重新登录了。效果是:刷新浏览器,就默认给我们登录成功。
    2. 关系
      1. 第三方认证系统,是独立于所有的应用系统的。
      2. 第三方认证系统的2个功能:
        1. 第1个:登录信息的校验,并且返回ticket
        2. 第2个:校验ticket是否合法
      3. 上面所说的ticket,就是前面提到的token(如access token,jwt token)。

七 springsecurity oathu2整合sso(单点登录)

  1. 概述
    1. 单点登录要求首先要有一个认证系统,这里使用8080:springsecurity oathu2项目做第三方认证系统。为什么呢?因为在项目springsecurity oathu2中,之前有配置1个认证(授权)服务器的配置。
    2. 那接下来呢,我们要去准备客户端,我们唯一要准备的也就是客户端了,其它的基本上不需要去准备。
    3. 上面单点登录的原理图中,有好多个应用系统123,每一个应用系统对于第三方认证系统而言都是一个客户端。但在这里就准备了一个应用系统1,因为它们的配置基本上是一样的。
  2. 详细步骤
    1. 8081:应用系统 + 用户资源
      1. 第一步:创建springboot项目
      2. 第二步:pom.xml,依赖
        1. springboot、spring web、spring test
        2. spring cloud、spring cloud springsecurity、spring cloud spring security oathu2
        3. jwt
      3. 第三步:application.properties
        server.port = 8081
        #如果有多个客户端的情况下,每个客户端的cookie的名称要不一致
        #防止 Cookie 冲突,冲突会导致登录验证不通过
        server.servlet.session.cookie.name = OAUTH2-CLIENT-SESSIONID01
        # 授权服务器地址
        oauth2-server-url : http : //localhost : 8080
        # 与授权服务器对应的配置
        security.oauth2.client.client-id = admin
        security.oauth2.client.client-secret = 112233
        security.oauth2.client.user-authorization-uri = ${oauth2-server
        url}/oauth/authorize
        security.oauth2.client.access-token-uri = ${oauth2-server-url}/oauth/token
        security.oauth2.resource.jwt.key-uri = ${oauth2-server-url}/oauth/token_key
      4. 第四步:准备“用户资源”
        1. 概述
          1. 为什么要准备"用户资源" 呢?因为我们要演示的是单点登录。什么叫单点登录呢?我们可以这样,为了去8081上获取用户资源。首先,得到8080上去进行授认证,认证成功再返回8081获取用户资源。
        2. 详细步骤
          1. package com.yjxxt.controller;
            import org.springframework.security.core.Authentication;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RestController;
            
            @RestController
            @RequestMapping("/user")
            public class UserController {
                
                @GetMapping("/getCurrentUser")
                public Object getCurrentUser(Authentication authentication) {
                    return authentication;
                }
            
            }
      5. 第五步:启动类加上注解:@EnableOAuth2Sso
    2. 8080:springsecurity oathu2项目(即授权服务器)
      1. 改造授权服务器配置类:AuthorizationServerConfig.java
        1. 第一步:重定向到客户端应用程序:.redirectUris("http://localhost:8081/login")
          1. 区别:之前在获取授权码时,重定向到www.baidu.com,.redirectUris("www.baidu.com")
        2. 第二步:自动授权:.autoApprove(true),即忽略授权网页,自动授权
          1. 区别:之前是我们的第三方登录都会有一个页面,然后你点击”授权“按钮后,才是真正的确认授权。但在实际项目中,我们想不用点击任何按钮就能授权。
        3. 第三步:获取密钥需要身份认证,使用单点登录时必须配置:
          @Override
          public void configure(AuthorizationServerSecurityConfigurer security) {
              // 获取密钥需要身份认证,使用单点登录时必须配置
              security.tokenKeyAccess("isAuthenticated()");
          }
    3. 验证:
      1. 第一步:重新启动授权服务器8080
      2. 第二步:重新启动应用系统8081
      3. 第三步:浏览器地址栏访问8081的用户资源接口:localhost:8081/user/getCurrentUser
      4. 第四步:自动跳转到的8080授权服务器去登录:http://localhost:8080/login
        1. 第a步:输入用户名和密码,点击登录按钮
      5. 第五步:自动跳回8081获取用户资源接口的信息:localhost:8081/user/getCurrentUser
      6. 注意:这样8080和8081来回跳,是不是就完成了跨域。
  3. 扩展:配置多个单点登录应用系统123
    1. 第一步:多个应用系统就照着上面的8081配置,有几个重点在这里重复说一下
      1. 第1步:启动类加上注解:@EnableOAuth2Sso
      2. 第2步:配置文件:application.properties
        1. 改一下下面3个配置,让它们唯一,这样你就是在配置了一个新的应用系统(客户端)了。:
          server.servlet.session.cookie.name=OAUTH2-CLIENT-SESSIONID01
          security.oauth2.client.client-id=admin
          security.oauth2.client.client-secret=112233
    2. 第二步:授权服务器
      1. 第1步:自动授权
      2. 第2步:重定向地址
      3. 第3步:配置多个应用系统:
      4. 第4步:必须要配置的,获取密钥需要身份认证,使用单点登录时必须配置:
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) {
            // 获取密钥需要身份认证,使用单点登录时必须配置
            security.tokenKeyAccess("isAuthenticated()");
        }

Spring Security 参考 1 第一部分前言 15 1.入门 16 2.介绍 17 2.1什么是Spring Security? 17 2.2历史 19 2.3版本编号 20 2.4获得Spring安全 21 2.4.1使用Maven 21 Maven仓库 21 Spring框架 22 2.4.2 Gradle 23 Gradle存储库 23 使用Spring 4.0.x和Gradle 24 2.4.3项目模块 25 核心 - spring-security-core.jar 25 远程处理 - spring-security-remoting.jar 25 Web - spring-security-web.jar 25 配置 - spring-security-config.jar 26 LDAP - spring-security-ldap.jar 26 ACL - spring-security-acl.jar 26 CAS - spring-security-cas.jar 26 OpenID - spring-security-openid.jar 26 测试 - spring-security-test.jar 26 2.4.4检出来源 26 3. Spring Security 4.2的新特性 27 3.1 Web改进 27 3.2配置改进 28 3.3杂项 28 4.样品和指南(从这里开始) 28 5. Java配置 29 5.1 Hello Web安全Java配置 29 5.1.1 AbstractSecurityWebApplicationInitializer 31 5.1.2 AbstractSecurityWebApplicationInitializer不存在Spring 31 5.1.3使用Spring MVC的AbstractSecurityWebApplicationInitializer 32 5.2 HttpSecurity 32 5.3 Java配置和表单登录 34 5.4授权请求 35 5.5处理注销 36 5.5.1 LogoutHandler 37 5.5.2 LogoutSuccessHandler 37 5.5.3更多注销相关参考 38 5.6认证 38 5.6.1内存认证 38 5.6.2 JDBC认证 39 5.6.3 LDAP认证 39 5.6.4 AuthenticationProvider 41 5.6.5 UserDetailsService 41 5.6.6 LDAP认证 41 5.7多个HttpSecurity 41 5.8方法安全性 43 5.8.1 EnableGlobalMethodSecurity 43 5.8.2 GlobalMethodSecurityConfiguration 44 5.9后处理配置的对象 45 5.10自定义DSL 46 6.安全命名空间配置 47 6.1简介 47 6.1.1命名空间的设计 49 6.2安全命名空间配置入门 50 6.2.1 web.xml配置 50 6.2.2最小的配置 50 6.2.3表单和基本登录选项 52 设置默认的登录目的地 54 6.2.4注销处理 54 6.2.5使用其他身份验证提供程序 55 添加密码编码器 56 6.3高级Web功能 56 6.3.1记得我认证 56 6.3.2添加HTTP / HTTPS通道安全 57 6.3.3会话管理 57 检测超时 57 并发会话控制 58 会话固定攻击保护 59 6.3.4 OpenID支持 60 属性交换 61 6.3.5响应头 62 6.3.6添加你自己的过滤器 62 设置一个自定义的AuthenticationEntryPoint 64 6.4方法安全 64 6.4.1 元素 65 使用protect-pointcut添加安全性切入点 66 6.5默认AccessDecisionManager 67 6.5.1自定义AccessDecisionManager 67 6.6验证管理器和命名空间 67 7.示例应用程序 69 7.1教程示例 69 7.2联系人 69 7.3 LDAP样本 71 7.4 OpenID示例 71 7.5 CAS样品 71 7.6 JAAS样品 72 7.7预认证样本 72 8. Spring Security社区 72 8.1问题跟踪 72 8.2成为参与 73 8.3更多信息 73 第二部分 架构与实现 73 9.技术概述 73 9.1运行环境 73 9.2核心组件 74 9.2.1 SecurityContextHolder,SecurityContext和认证对象 74 获取有关当前用户的信息 75 9.2.2 UserDetailsService 75 9.2.3授予权力 77 9.2.4总结 77 9.3认证 78 9.3.1什么是Spring Security中的认证? 78 9.3.2直接设置SecurityContextHolder内容 80 9.4 Web应用程序中的身份验证 81 9.4.1 ExceptionTranslationFilter 82 9.4.2 AuthenticationEntryPoint 82 9.4.3认证机制 82 9.4.4在请求之间存储SecurityContext 83 9.5 Spring Security中的访问控制(授权) 84 9.5.1安全和AOP建议 84 9.5.2安全对象和AbstractSecurityInterceptor 85 什么是配置属性? 85 RunAsManager 86 AfterInvocationManager 86 扩展安全对象模型 87 9.6本地化 87 10.核心服务 89 10.1 AuthenticationManager,ProviderManager和AuthenticationProvider 89 10.1.1成功认证时清除证书 91 10.1.2 DaoAuthenticationProvider 91 10.2 UserDetailsService实现 92 10.2.1内存认证 92 10.2.2 JdbcDaoImpl 93 权威组织 94 10.3密码编码 94 10.3.1什么是散列? 95 10.3.2添加盐到哈希 95 10.3.3散列和认证 96 10.4Jackson 支持 96 第三部分 测试 97 11.测试方法安全性 97 11.1安全测试设置 98 11.2 @WithMockUser 98 11.3 @WithAnonymousUser 100 11.4 @用户详细信息 101 11.5 @WithSecurityContext 102 11.6测试元注释 104 12. Spring MVC测试集成 104 12.1设置MockMvc和Spring Security 104 12.2 SecurityMockMvcRequestPostProcessors 105 12.2.1使用CSRF保护进行测试 105 12.2.2在Spring MVC测试中以用户身份运行测试 106 12.2.3使用RequestPostProcessor在Spring MVC测试中以用户身份运行 106 作为用户在Spring MVC测试中使用注释运行 108 12.2.4测试HTTP基本认证 109 12.3 SecurityMockMvcRequestBuilders 109 12.3.1测试基于表单的认证 109 12.3.2测试注销 110 12.4 SecurityMockMvcResultMatchers 110 12.4.1未经认证的声明 111 12.4.2认证断言 111 第四部分 Web应用程序安全 112 13.安全过滤器链 112 13.1 DelegatingFilterProxy 112 13.2 FilterChainProxy 113 13.2.1绕过滤网链 115 13.3过滤器排序 115 13.4请求匹配和HttpFirewall 116 13.5与其他基于过滤器的框架一起使用 118 13.6高级命名空间配置 118 14.核心安全筛选器 119 14.1 FilterSecurityInterceptor 119 14.2 ExceptionTranslationFilter 121 14.2.1 AuthenticationEntryPoint 122 14.2.2 AccessDeniedHandler 122 14.2.3 SavedRequest和RequestCache接口 123 14.3 SecurityContextPersistenceFilter 123 14.3.1 SecurityContextRepository 124 14.4 UsernamePasswordAuthenticationFilter 125 14.4.1认证成功与失败的应用流程 125 15. Servlet API集成 127 15.1 Servlet 2.5+集成 127 15.1.1 HttpServletRequest.getRemoteUser() 127 15.1.2 HttpServletRequest.getUserPrincipal() 127 15.1.3 HttpServletRequest.isUserInRole(String) 128 15.2 Servlet 3+集成 128 15.2.1 HttpServletRequest.authenticate(HttpServletResponse) 128 15.2.2 HttpServletRequest.login(String,String) 129 15.2.3 HttpServletRequest.logout() 129 15.2.4 AsyncContext.start(Runnable) 129 15.2.5异步Servlet支持 130 15.3 Servlet 3.1+集成 131 15.3.1 HttpServletRequest#changeSessionId() 132 16.基本和摘要式身份验证 132 16.1 BasicAuthenticationFilter 132 16.1.1配置 132 16.2 DigestAuthenticationFilter 133 16.2.1配置 135 17.记住我的身份验证 136 17.1概述 136 17.2简单的基于哈希的令牌方法 136 17.3持久性令牌方法 137 17.4记住我的接口和实现 138 17.4.1 TokenBasedRememberMeServices 138 17.4.2 PersistentTokenBasedRememberMeServices 139 18.跨站点请求伪造(CSRF) 140 18.1 CSRF攻击 140 18.2同步器令牌模式 141 18.3何时使用CSRF保护 142 18.3.1 CSRF保护和JSON 142 18.3.2 CSRF和无状态浏览器应用程序 143 18.4使用Spring Security CSRF保护 143 18.4.1使用适当的HTTP动词 144 18.4.2配置CSRF保护 144 18.4.3包含CSRF令牌 145 表单提交 145 Ajax和JSON请求 145 CookieCsrfTokenRepository 146 18.5 CSRF警告 147 18.5.1超时 148 18.5.2登录 148 18.5.3注销 149 18.5.4多部分(文件上传) 149 在Spring Security之前放置MultipartFilter 150 包含CSRF令牌 151 18.5.5隐藏的HttpMethodFilter 151 18.6覆盖默认值 151 19. CORS 152 20.安全性HTTP响应头 154 20.1默认的安全头 154 20.1.1缓存控制 157 20.1.2内容类型选项 158 20.1.3 HTTP严格传输安全(HSTS) 159 20.1.4 HTTP公钥密码(HPKP) 161 20.1.5 X-Frame-Options 163 20.1.6 X-XSS保护 164 20.1.7内容安全策略(CSP) 165 配置内容安全策略 166 其他资源 168 20.1.8推荐人政策 168 配置引用者策略 169 20.2自定义标题 169 20.2.1静态头 169 20.2.2标题作者 170 20.2.3 DelegatingRequestMatcherHeaderWriter 171 21.会议管理 172 21.1 SessionManagementFilter 173 21.2 SessionAuthenticationStrategy 173 21.3并发控制 174 21.3.1查询当前通过身份验证的用户及其会话的SessionRegistry 176 22.匿名身份验证 177 22.1概述 177 22.2配置 178 22.3 AuthenticationTrustResolver 179 23. WebSocket安全 180 23.1 WebSocket配置 181 23.2 WebSocket身份验证 182 23.3 WebSocket授权 182 23.3.1 WebSocket授权说明 183 消息类型的WebSocket授权 184 目的地上的WebSocket授权 184 23.3.2出站消息 185 23.4执行相同的来源政策 185 23.4.1为什么同源? 185 23.4.2 Spring WebSocket允许的来源 186 23.4.3添加CSRF到Stomp头 186 23.4.4在WebSockets中禁用CSRF 187 23.5使用SockJS 187 23.5.1 SockJS和框架选项 187 23.5.2轻松放松CSRF 188 第五部分授权 190 24.授权体系结构 190 24.1当局 190 24.2预调用处理 191 24.2.1 AccessDecisionManager 191 24.2.2基于投票的AccessDecisionManager实现 192 RoleVoter 193 AuthenticatedVoter 194 自定义选民 194 24.3调用处理后 194 24.4分层角色 196 25.安全的对象实现 197 25.1 AOP联盟(MethodInvocation)安全拦截器 197 25.1.1显式MethodSecurityInterceptor配置 197 25.2 AspectJ(JoinPoint)安全拦截器 198 26.基于表达式的访问控制 200 26.1概述 200 26.1.1通用内置表达式 201 26.2网络安全表达式 202 26.2.1在Web安全表达式中引用Bean 203 26.2.2 Web安全表达式中的路径变量 204 26.3方法安全表达式 204 26.3.1 @Pre和@Post注释 205 访问控制使用@PreAuthorize和@PostAuthorize 205 使用@PreFilter和@PostFilter进行过滤 207 26.3.2内置表达式 207 PermissionEvaluator接口 208 方法安全元注释 209 第六部分 其他主题 209 27.域对象安全(ACL) 209 27.1概述 209 27.2重要概念 211 27.3入门 214 28.预认证方案 216 28.1预认证框架类 216 28.1.1 AbstractPreAuthenticatedProcessingFilter 217 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 217 28.1.2 PreAuthenticatedAuthenticationProvider 218 28.1.3 Http403ForbiddenEntryPoint 218 28.2具体实施 219 28.2.1请求头认证(Siteminder) 219 Siteminder示例配置 219 28.2.2 Java EE容器认证 220 29. LDAP认证 220 29.1概述 220 29.2在Spring Security中使用LDAP 221 29.3配置LDAP服务器 221 29.3.1使用嵌入式测试服务器 222 29.3.2使用绑定认证 222 29.3.3加载权限 223 29.4实现类 223 29.4.1 LdapAuthenticator实现 224 通用功能 224 认证者 225 PasswordComparisonAuthenticator 225 29.4.2连接到LDAP服务器 225 29.4.3 LDAP搜索对象 225 FilterBasedLdapUserSearch中 225 29.4.4 LdapAuthoritiesPopulator 226 29.4.5 Spring Bean配置 226 29.4.6 LDAP属性和定制的UserDetails 227 29.5 Active Directory认证 228 29.5.1 ActiveDirectoryLdapAuthenticationProvider 228 活动目录错误代码 229 30. JSP标签库 230 30.1声明Taglib 230 30.2授权标签 230 30.2.1禁用测试的标签授权 231 30.3认证标签 232 30.4 accesscontrollist标签 232 30.5 csrfInput标签 233 30.6 csrfMetaTags标签 233 31 Java认证和授权服务(JAAS)提供者 235 31.1概述 235 31.2摘要:Java认证提供者 235 31.2.1 JAAS CallbackHandler 235 31.2.2 JAAS权威机构 236 31.3 DefaultJaasAuthenticationProvider 237 31.3.1 InMemoryConfiguration 237 31.3.2 DefaultJaasAuthenticationProvider示例配置 238 31.4 JaasAuthenticationProvider 239 31.5作为主题运行 240 32. CAS认证 240 32.1概述 240 32.2 CAS的工作原理 240 32.2.1 Spring安全和CAS交互序列 241 32.3 CAS客户端的配置 244 32.3.1服务票据认证 244 32.3.2单一注销 246 32.3.3使用CAS认证无状态服务 249 配置CAS以获取代理授予票证 249 使用代理票证调用无状态服务 250 32.3.4代理票证认证 251 33. X.509认证 253 33.1概述 253 33.2将X.509身份验证添加到您的Web应用程序 253 33.3在Tomcat中设置SSL 254 34.运行认证替换 255 34.1概述 255 34.2配置 255 35. Spring Security加密模块 257 35.1简介 257 35.2加密器 257 35.2.1 BytesEncryptor 257 35.2.2 TextEncryptor 258 35.3关键发电机 258 35.3.1 BytesKeyGenerator 258 35.3.2 StringKeyGenerator 259 35.4密码编码 259 36.并发支持 260 36.1 DelegatingSecurityContextRunnable 260 36.2 DelegatingSecurityContextExecutor 262 36.3 Spring安全性并发类 264 37. Spring MVC集成 265 37.1 @EnableWebMvcSecurity 265 37.2 MvcRequestMatcher 265 37.3 @AuthenticationPrincipal 268 37.4 Spring MVC异步集成 271 37.5 Spring MVC和CSRF集成 271 37.5.1自动令牌包含 271 37.5.2解析CsrfToken 272 第七部分 Spring数据集成 273 38. Spring Data&Spring安全配置 273 39. @Query中的安全表达式 273 第八部分 附录 274 40.安全数据库模式 274 40.1用户模式 274 40.1.1集团当局 274 40.2持久登录(记得我)架构 275 40.3 ACL模式 275 40.3.1 HyperSQL 276 40.3.2 PostgreSQL 277 40.3.3 MySQL和MariaDB 278 40.3.4 Microsoft SQL Server 279 40.3.5 Oracle数据库 280 41.安全命名空间 282 41.1 Web应用程序安全性 282 41.1.1 282 41.1.2 282 属性 283 的子元素 285 41.1.3 286 的父元素 286 属性 286 41.1.4 286 属性 287 父元素 287 41.1.5 <headers> 287 <headers>属性 288 <headers>的父元素 288 <headers>的子元素 288 41.1.6 289 属性 289 的父元素 289 41.1.7 289 属性 289 的父元素 290 41.1.8 290 属性 290 的父元素 290 41.1.9 290 的子元素 290 41.1.10 291 属性 291 的父元素 291 41.1.11 291 属性 291 的父元素 291 41.1.12 291 属性 292 的父元素 292 41.1.13 <frame-options> 292 <frame-options>属性 292 <frame-options>的父元素 293 41.1.14 [removed] 293 [removed]属性 293 [removed]的父元素 294 41.1.15 294 属性 294 的父元素 294 41.1.16 <header> 294 <header-attributes>属性 294 <header>的父元素 295 41.1.17 295 的父元素 295 属性 295 41.1.18 295 父元素 296 属性 296 41.1.19 296 的父元素 296 属性 296 41.1.20 <expression-handler> 297 <expression-handler>的父元素 297 属性 297 41.1.21 <form-login> 297 <form-login>的父元素 298 <form-login>属性 298 41.1.22 299 的父元素 300 属性 300 41.1.23 元素 300 属性 300 41.1.24 300 的父元素 300 属性 301 41.1.25 302 的父元素 302 属性 302 41.1.26 302 父元素 302 属性 303 41.1.27 303 的父元素 303 属性 303 的子元素 305 41.1.28 305 的父元素 305 属性 305 的子元素 305 41.1.29 306 的父元素 306 属性 306 41.1.30 306 的父元素 306 的子元素 307 41.1.31 307 的父元素 307 属性 307 41.1.32 307 的父元素 307 属性 307 41.1.33 元素 309 的父元素 309 属性 309 41.1.34 309 的父元素 309 属性 309 的子元素 310 41.1.35 311 的父元素 311 属性 311 41.1.36 312 的父元素 312 属性 312 41.1.37 313 属性 313 的子元素 313 41.1.38 313 的父元素 313 属性 313 41.1.39 314 属性 314 的子元素 314 41.2 WebSocket安全 314 41.2.1 315 属性 315 的子元素 316 41.2.2 316 的父元素 316 属性 316 41.3认证服务 317 41.3.1 317 属性 317 的子元素 317 41.3.2 318 的父元素 318 属性 318 的子元素 318 41.3.3 319 属性 319 41.3.4 320 的父元素 320 属性 320 的子元素 320 41.3.5 320 的父元素 321 属性 321 41.3.6 321 属性 321 的子元素 321 41.3.7 321 的父元素 322 属性 322 41.4方法安全 322 41.4.1 322 属性 322 的子元素 324 41.4.2 324 的父元素 324 属性 324 41.4.3 324 的父元素 325 325 41.4.4 325 的父元素 325 属性 325 41.4.5 325 的父元素 325 属性 325 41.4.6 326 的父元素 326 属性 326 41.4.7使用安全方法 326 父节点 326 属性 326 41.4.8 326 属性 327 的子元素 327 41.4.9 327 属性 327 的子元素 327 41.4.10 327 父元素 328 属性 328 41.5 LDAP名称空间选项 328 41.5.1使用。定义LDAP服务器 328 属性 329 41.5.2 329 的父元素 329 属性 329 的子元素 331 41.5.3 331 的父元素 331 属性 332 的子元素 332 41.5.4 332 属性 332 42.春季安全依赖 333 42.1 spring-security-core 334 42.2 spring-security-remoting 334 42.3 spring-security-web 335 42.4 spring-security-ldap 335 42.5 spring-security-config 336 42.6 spring-security-acl 336 42.7 spring-security-cas 337 42.8 spring-security-openid 337 42.9 spring-security-taglibs 338 43.代理服务器配置 338 44. Spring Security FAQ 339 44.1一般问题 339 44.1.1 Spring Security是否会处理我所有的应用程序安全要求? 339 44.1.2为什么不使用web.xml安全? 339 44.1.3需要哪些Java和Spring Framework版本? 341 44.1.4我是Spring Security的新手,我需要构建一个支持通过HTTPS进行CAS单点登录的应用程序,同时允许对某些URL进行本地基本身份验证,并对多个后端用户信息源(LDAP和JDBC)进行身份验证。我已经复制了一些我发现的配置文件,但不起作用。什么可能是错的? 341 44.2常见问题 342 44.2.1当我尝试登录时,我收到一条错误消息,指出“Bad Credentials”。怎么了? 343 44.2.2当我尝试登录时,我的应用程序进入“无限循环”,发生了什么事? 344 44.2.3我收到一条异常消息“访问被拒绝(用户是匿名的)”。怎么了? 344 44.2.4即使在我退出应用程序之后,为什么还能看到安全的页面? 345 44.2.5我得到一个异常,消息“在SecurityContext中没有找到认证对象”。怎么了? 345 44.2.6我无法使LDAP认证正常工作。我的配置有什么问题? 345 44.2.7会话管理 346 44.2.8我使用Spring Security的并发会话控制来防止用户一次登录多次。登录后打开另一个浏览器窗口时,不会阻止我再次登录。为什么我可以多次登录? 347 44.2.9为什么在通过Spring Security进行身份验证时会话ID发生了变化? 347 44.2.10我正在使用Tomcat(或其他一些servlet容器),并为我的登录页面启用了HTTPS,之后切换回HTTP。这是行不通的 - 我只是在认证之后回到登录页面。 347 44.2.11我没有在HTTP和HTTPS之间切换,但是我的会话仍然丢失 348 44.2.12我试图使用并发会话控制支持,但是不会让我重新登录,即使我确定我已经注销并且没有超出允许的会话。 348 44.2.13 Spring Security正在创建一个会话,即使我已经配置了它,通过设置create-session属性为永远不会。 348 44.2.14执行POST时,我得到了一个403 Forbidden 349 44.2.15我正在使用RequestDispatcher将请求转发到另一个URL,但是我的安全限制没有被应用。 349 44.2.16我已经将Spring Security的元素添加到我的应用程序上下文中,但是如果将安全注释添加到我的Spring MVC控制器bean(Struts操作等)中,那么它们似乎没有效果。 349 44.2.17我有一个肯定被认证的用户,但是当我在一些请求期间尝试访问SecurityContextHolder时,认证是空的。为什么我看不到用户信息? 350 44.2.18在使用URL属性时,授权JSP标记不尊重我的方法安全注释。 350 44.3 Spring安全体系结构问题 350 44.3.1我如何知道X是哪个包? 350 44.3.2名称空间元素如何映射到传统的bean配置? 351 44.3.3“ROLE_”是什么意思,为什么我的角色名字需要它? 351 44.3.4如何知道添加到我的应用程序中的哪些依赖关系与Spring Security一起使用? 352 44.3.5运行嵌入式ApacheDS LDAP服务器需要哪些依赖关系? 352 44.3.6什么是UserDetailsService,我需要一个吗? 353 44.4共同的“Howto”请求 353 44.4.1我需要登录更多的信息,而不仅仅是用户名。如何添加对额外登录字段(例如公司名称)的支持? 354 44.4.2如果只有所请求的URL的片段值不同(例如/ foo#bar和/ foo#blah),我该如何应用不同的拦截url链接? 354 44.4.3如何在UserDetailsService中访问用户的IP地址(或其他Web请求数据)? 354 44.4.4如何从UserDetailsService访问HttpSession? 355 44.4.5如何在UserDetailsService中访问用户的密码? 355 44.4.6如何动态定义应用程序中的安全URL? 355 44.4.7如何针对LDAP进行身份验证,但从数据库加载用户角色? 357 44.4.8我想修改由命名空间创建的bean的属性,但是模式中没有任何东西支持它。我可以做什么放弃命名空间的使用? 358 45.从3.x迁移到4.x 359
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值