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的配置与应用,实现服务注册机制。

相关推荐
Theodore_10224 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸5 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象5 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了6 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·6 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王6 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康7 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
qq_17448285757 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
转世成为计算机大神7 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式