当前位置: 首页 > news >正文

Springboot 实践(9)springboot集成Oauth2.0授权包,5个接口文件配置详解

        前文讲解实现了spring boot集成Oauth2.0,实现了授权服务器和资源服务器的搭建,并通过浏览器和postman测试,获取到了授权码,用携带授权码的URL能够争取范文到资源。

本文详细讲解spring boot集成Oauth2.0的几个重要文件接口,详细如下:

1、授权服务配置接口AuthorizationServerConfigurerAdapter

AuthorizationServerConfigurer接口,其中存在3个方法:

☆ AuthorizationServerSecurityConfigurer:配置令牌端点(Token Endpoint)的安全约束;

☆ ClientDetailsServiceConfigurer:配置OAuth2客户端;

☆ AuthorizationServerEndpointsConfigurer:配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services);

详细代码如下:bleAuthorizationServer

public class OAuthAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired

    private DataSource dataSource;

    @Autowired

    private AuthenticationManager authenticationManager;

    @Autowired

    private OAuthWebSecurityConfig oauthWebSecurityConfig;

   

  //AuthorizationServerSecurityConfigurer:配置令牌端点(Token Endpoint)的安全约束;

  //AuthorizationServerSecurityConfigurer继承自SecurityConfigurerAdapter,也就是一个 Spring Security安全配置提供给AuthorizationServer去配置AuthorizationServer的端点(/oauth/****)的安全访问规则、过滤器Filter。

    @Override

    public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

        oauthServer

        .tokenKeyAccess("permitAll()")//客户端token调用许可

        .checkTokenAccess("permitAll()")//客户端校验token访问许可

       .allowFormAuthenticationForClients();       

    }

   

    //refresh_token 单独配置UserDetailsService

    @Bean

    public UserDetailsService userDetailsServiceRefresh_token() { 

        return oauthWebSecurityConfig.userDetailsService();

}

    //AuthorizationServerEndpointsConfigurer:配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services);

    @Override

    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints // 设置令牌   

                .tokenStore(new JdbcTokenStore(dataSource)).userDetailsService(userDetailsServiceRefresh_token())

                .authenticationManager(authenticationManager);

    }

    @Bean // 声明 ClientDetails实现

    public ClientDetailsService clientDetailsService() {

        return new JdbcClientDetailsService(dataSource);

    }   

    //ClientDetailsServiceConfigurer:配置OAuth2客户端;

    @Override

    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {

        clients.withClientDetails(clientDetailsService());

    }   

}

2、资源服务配置接口ResourceServerConfigurerAdapter

        ResourceServerConfigurerAdapter (资源服务器配置)内部关联了ResourceServerSecurityConfigurer 和 HttpSecurity。前者与资源安全配置相关,后者与http安全配置相关,详细代码如下:

/*** 资源服务器配置*/

@Configuration

@EnableResourceServer

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

@Order(-1)

public class OAuthResourcesServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired

    private DataSource dataSource;     

    //在每个ResourceServer实例上设置resourceId,该resourceId作为该服务资源的唯一标识。(假如同一个微服务资源部署多份,resourceId相同)

    private static final String DEMO_RESOURCE_ID = "test-resource";

    @Override

    public void configure(ResourceServerSecurityConfigurer resources) {

       resources.resourceId(DEMO_RESOURCE_ID);  //配置resourceServerID

       resources.tokenStore(new JdbcTokenStore(dataSource)); //...... 还可以有有其他的配置 

    }

    @Override

    public void configure(HttpSecurity http) throws Exception {

        http   

            .cors()//开启跨域

            .and()

            .csrf().disable()

            .logout()

            .logoutUrl("/logout")//虚拟的登出地址

            .and()

            .authorizeRequests()

            .antMatchers("/loginSuccess").permitAll()

            .antMatchers("/loginSuccess.html").permitAll()

            .antMatchers("/actuator/health").permitAll()

            .anyRequest().authenticated();

    }

}

3、web安全配置接口WebSecurityConfigurerAdapter

WebSecurityConfigurerAdapter是Spring Security提供了一个抽象类,实现了默认的认证和授权,允许用户自定义一个WebSecurity类,重写其中的三个configure来实现自定义的认证和授权,这三个方法如下:

  • 自定义身份认证的逻辑

protected void configure(AuthenticationManagerBuilder auth) throws Exception { }

  • 自定义全局安全过滤的逻辑

public void configure(WebSecurity web) throws Exception { }

  • 自定义URL访问权限的逻辑

protected void configure(HttpSecurity http) throws Exception { }

详细代码如下:

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

@Order(-1)

public class OAuthWebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired

  private MyUserDetailServiceImpl myUserDetailServiceImpl;

  @Autowired

  private LogoutSuccessHandlerImpl logoutSuccessHandler;

  @Autowired

  private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

  @Autowired

  private DataSource dataSource;

  /** * @return RememberMe 功能的 Repository */

  @Bean

  public PersistentTokenRepository persistentTokenRepository() {

      // 连接数据库的实现类,还有一个实现类时存内存的InMemoryTokenRepositoryImpl

      JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();

      // 配置数据源

      tokenRepository.setDataSource(dataSource);

      // 在启动数据库时创建存储token的表

      //tokenRepository.setCreateTableOnStartup(true);

      return tokenRepository;

  }

  /******************************remember me***********************************/

  @Override

    @Bean

    public AuthenticationManager authenticationManagerBean() throws Exception {

        return super.authenticationManagerBean();

    }

  /** 放行静态资源 */

  @Override

    public void configure(WebSecurity web) throws Exception {

      web.ignoring().antMatchers("/swagger-ui.html");

      web.ignoring().antMatchers("/swagger-resources/**");

      web.ignoring().antMatchers("/v2/api-docs");

      web.ignoring().antMatchers("/configuration/security");

      web.ignoring().antMatchers("/configuration/ui");

      //web.ignoring().antMatchers("/webjars/springfox-swagger-ui/**");

     

      /************************************************************

       * servlet 3.0 以上的版本支持直接访问 jar 包里面的资源文件。

       * 访问方式:将 jar 包里的 META-INF/resources 目录看成根目录,

       * 则这个目录下的文件都可以直接访问

       * swagger-bootstrap-ui-1.9.6.jar资源放行*/

      web.ignoring().antMatchers("/webjars/**");

      web.ignoring().antMatchers("/doc.html");

     

      web.ignoring().antMatchers("/loginSuccess");

      web.ignoring().antMatchers("/loginSuccess.html");

      web.ignoring().antMatchers("/loginError");

      web.ignoring().antMatchers("/lock");

      web.ignoring().antMatchers("/assets/**");

      //路由跳转允许

      web.ignoring().antMatchers("/api/**");

      web.ignoring().antMatchers("/websocket/**"); //农村饮水安全

      web.ignoring().antMatchers("/Serialnum/EnSure"); //序列号确认

      web.ignoring().antMatchers("/lock"); //锁屏页面

      web.ignoring().antMatchers("/login.html"); //序列号确认

      //放行consul安全监测接口

      web.ignoring().antMatchers("/v1");

      web.ignoring().antMatchers("/actuator/health");

      //web.ignoring().antMatchers("/loginError.html");

      web.ignoring().antMatchers("/favicon.ico");

      //放行单点登录

      web.ignoring().antMatchers("/index");

      web.ignoring().antMatchers("/index/**");

      web.ignoring().antMatchers("/index/oauth_callback");

      //web.ignoring().antMatchers("/myLogout");

     

    }

    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http       

        .requestMatchers().antMatchers(HttpMethod.OPTIONS,"/login", "/oauth/authorize", "/oauth/token")

        .and()

        .cors()//开启跨域

      .and()

      .csrf().disable()              

        .requestMatchers()       

        .antMatchers("/login")

        .antMatchers(HttpMethod.OPTIONS)

        .antMatchers("/oauth/authorize")

        .and()    

      .rememberMe()//记住我相关配置

      .tokenRepository(persistentTokenRepository())

      .tokenValiditySeconds(60*60*10)

        //.antMatchers("/oauth/token")

        .and()           

        .authorizeRequests()

        .anyRequest().authenticated()

        .and()

        .formLogin()

        .loginPage("/login")

           // 自定义登录页面,这里配置了 loginPage, 就会通过 LoginController 的 login 接口加载登录页面

        // 登入成功后,跳转至指定页面

        //.defaultSuccessUrl("/loginSuccess")

        .failureUrl("/loginError").permitAll()       

        .and()

        .logout()

        .logoutUrl("/logout")//虚拟的登出地址

        .logoutSuccessHandler(logoutSuccessHandler);

       

        http.formLogin().failureHandler(customAuthenticationFailureHandler);

    }

   

    @Bean

    @Override

    public UserDetailsService userDetailsService(){

        return myUserDetailServiceImpl;

        //return userAuthenticationProvider;

    }

   

    @Override

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 配置用户名密码,这里采用内存方式,生产环境需要从数据库获取   

//        auth.inMemoryAuthentication()

//            .withUser("admin")

//            .password(passwordEncoder().encode("123"))          

//            .roles("USER");

     

        // 使用自定义认证与授权

        auth.userDetailsService(userDetailsService());

    }

    @Bean

    public BCryptPasswordEncoder passwordEncoder(){

        return new BCryptPasswordEncoder();

    }

}

4、用户登录服务接口UserDetailsService

        Spring Security中进行身份验证的是AuthenticationManager接口,ProviderManager是它的一个默认实现,但它并不用来处理身份认证,而是委托给配置好的AuthenticationProvider,每个AuthenticationProvider会轮流检查身份认证。检查后或者返回Authentication对象或者抛出异常。验证身份就是加载响应的UserDetails,看看是否和用户输入的账号、密码、权限等信息匹配。UserDetails中需要重定义loadUserByUsername()函数。

详细代码如下:

@Component

public class MyUserDetailServiceImpl implements UserDetailsService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired

    private SysUserService sysUserService;

    @Autowired

    private SysUserMapper sysUserMapper;

    /**

     * @param username

     * @return

     * @throws UsernameNotFoundException

     */

    @Override

    public UserDetails loadUserByUsername(String username) {

        //1.根据用户名去数据库去查询用户信息获取加密后的密码         

        SysUser sysUser = sysUserMapper.findByName(username);

        if(sysUser==null) {

            logger.info("-------------未查询到用户名:" + username);

            throw new UsernameNotFoundException("Invalid username or password.");

        }else {        

             Boolean stateStr=sysUser.getAccountNonLocked();//锁定状态

            if(stateStr==false){//用户被锁定

                long lockTime = sysUser.getLockTime();

                long sysTime = System.currentTimeMillis();

                long time = sysTime - lockTime;

                if(time>=10*60*1000) { //时间超过10分钟,解锁账户

                    sysUserMapper.updateUNLockedByUserId(username);

                    sysUserMapper.updatelockTimeByUserId(username, 0L);

                    sysUserMapper.updatenLockByUserId(username, 0L);

                    stateStr=true;

                }else {

                    throw new InternalAuthenticationServiceException("该账号已被锁定,请联系管理员!");

                }               

             }

           

            Set<String> permissions = sysUserService.findPermissions(username);        

            List<GrantedAuthority> grantedAuthorities = permissions.stream().map(GrantedAuthorityImpl::new).collect(Collectors.toList());

                        

            return new User(username,

                    //encryptedPassWord,

                    sysUser.getPassword(),

                    true,

                    true,

                    true,

                    stateStr, //锁定状态               

                    grantedAuthorities);

        }         

    } 

}

5、授权失败接口SimpleUrlAuthenticationFailureHandler

        在Spring Security Web框架内部,缺省使用的认证错误处理策略是AuthenticationFailureHandler的实现类SimpleUrlAuthenticationFailureHandler。它由配置指定一个defaultFailureUrl,表示认证失败时缺省使用的重定向地址。一旦认证失败,它的方法onAuthenticationFailure被调用时,它就会将用户重定向到该地址。如果该属性没有设置,它会向客户端返回一个401状态码。另外SimpleUrlAuthenticationFailureHandler还有一个属性useForward,如果该属性设置为true,页面跳转将不再是重定向(redirect)机制,取而代之的是转发(forward)机制。

该处只需要重定义onAuthenticationFailure()详细代码如下:

//3、将登录失败提示到前端展示

@Component

public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

  private Logger logger = LoggerFactory.getLogger(this.getClass());

  private  static ObjectMapper objectMapper = new ObjectMapper();

  @Autowired

  private ThymeleafViewResolver viewResolver;

  private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

   

  @Override

  public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {        

  //此处自行定义授权失败功能。

  }

}

        springboot集成Oauth2.0授权包,接口文件配置详解到此就结束了,学友在实际操作过程中遇到问题,欢迎联系博主。

下文讲解spring cloud的配置与应用,实现服务注册机制。

http://www.lryc.cn/news/131024.html

相关文章:

  • 最新AI系统ChatGPT程序源码/支持GPT4/自定义训练知识库/GPT联网/支持ai绘画(Midjourney)+Dall-E2绘画/支持MJ以图生图
  • 【高频面试题】 消息中间件
  • 物联网智慧安防实训综合实训基地建设方案
  • openGauss学习笔记-44 openGauss 高级数据管理-存储过程
  • 【Linux】进程信号篇Ⅲ:可重入函数、volatile关键字、SIGCHLD信号
  • 排序算法:冒泡排序
  • Spring事件监听源码解析
  • Cpp学习——list的模拟实现
  • 工具推荐:Chat2DB一款开源免费的多数据库客户端工具
  • C语言刷题指南(二)
  • [C++11]
  • 【MySQL系列】--初识数据库
  • Unity导入google.protobuf失败,无法找到google命名空间
  • 使用IDM下载视频出现“由于法律原因,IDM无法下载...
  • pointnet C++推理部署--tensorrt框架
  • 34.Netty源码之Netty如何处理网络请求
  • vscode 安装勾选项解释
  • Spring 6.0官方文档示例(24): replace-method的用法
  • 自然语言处理从入门到应用——LangChain:记忆(Memory)-[聊天消息记录]
  • Python web实战之细说 Django 的单元测试
  • pytorch 42 C#使用onnxruntime部署内置nms的yolov8模型
  • 【Lua】(一)VSCode 搭建 Lua 开发环境
  • react-vite-antd环境下新建项目
  • KeilMDk软仿真设置_STM32F03C8
  • mysql的隐式连接和显式连接的区别
  • vue-element-admin新增view后点击侧边栏加载慢问题
  • 论文《LoRA: Low-Rank Adaptation of Large Language Models》阅读
  • MySQL数据类型篇
  • Eureka注册中心
  • 代码随想录算法训练营第53天|动态规划part14