springcloud 微服务鉴权_搭建SpringCloud微服务框架:四、Spring-Security-OAuth 服务接口鉴权...

本文介绍了如何在SpringCloud微服务框架中使用OAuth2进行接口鉴权,详细讲解了密码模式和客户端模式,并提供了配置及代码示例,包括Redis和MySQL的数据存储。通过设置不同授权模式,实现安全的资源访问控制。
摘要由CSDN通过智能技术生成

搭建微服务框架(服务接口鉴权)

前面已经可以通过SpringCloud可以来构建对外的接口,现在来介绍一下怎么通过使用OAuth2来进行接口的鉴权。

Github地址:SQuid

介绍

OAuth2网上介绍的例子太多太多,简单点介绍它就是一个授权的标准。

OAuth2目前拥有四种授权机制:

授权码模式(authorization code)

授权码模式大多数用于互联网登录的场景,比如在京东商城网站中,使用QQ号进行授权登录:

简化模式(implicit)

一般很少用到,目前对这种模式自己也没有代码上的实现,所以还是不进行叙述,免得误人子弟了?

密码模式(resource owner password credentials)

密码模式对于一般的企业B/S架构系统用到的非常多,毕竟系统中已经存储了用户名和密码,而密码模式则就是需要提供用户名和密码。客户端使用这些信息,向“服务商提供商(也就是企业开发的系统)”索要授权。

客户端模式(client credentials)

客户端模式多用于对第三方接口的使用,分配给对方一个secret就行,用对方来进行acess_token的获取。

关键名词说明:

client_id :客户端的Id。

access_token : 授权成功后返回的token。

expires_in : 过期时间。

refresh_token : access_token即将过期,或者access_token丢失,可以使用refresh_token重新获取。

scope : 本次申请权限的范围。

grant_type : 授权的类型,填写对应的授权机制定义的名词。

本次集成的是 Spring Security OAuth,集成后的项目仅支持 密码模式 和 客户端模式 两种。

使用Spring Security OAuth

在集成OAuth时,我们需要拥有以下环境:

Mysql5.7+

MySQL用来记录OAuth的必要信息: client_id、clien_secret、grant、scope,SQL脚本地址:oauth2.sql

Redis

Redis则用来控制 access_token 的有效期。

新建工程

首先我们先在原有的工程下新建一个 squid-oatuh2 的工程,引入下列maven依赖:

org.springframework.security.oauth

spring-security-oauth2

2.3.3.RELEASE

org.springframework.cloud

spring-cloud-starter-security

org.springframework.boot

spring-boot-starter-data-redis

mysql

mysql-connector-java

org.springframework

spring-jdbc

com.alibaba.cloud

spring-cloud-alibaba-nacos-discovery

com.alibaba.cloud

spring-cloud-alibaba-nacos-config

引入依赖后,我们开始编写使用OAuth的代码,为了方便,我先将我的工程截图:

紧接着,贴下代码:

AuthResourceConfig

@EnableResourceServer

@Configuration

public class AuthResourceConfig extends ResourceServerConfigurerAdapter {

@Autowired

RedisConnectionFactory redisConnectionFactory;

// @Autowired

// DataSource dataSource;

@Override

public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

super.configure(resources);

}

@Override

public void configure(HttpSecurity http) throws Exception {

http.

csrf().disable()

.authorizeRequests().anyRequest().authenticated()

.and()

.httpBasic();

}

// @Bean

// ResourceServerTokenServices resourceServerTokenServices() {

// RemoteTokenServices tokenServices = new RemoteTokenServices();

// tokenServices.setCheckTokenEndpointUrl("http://localhost:8081/oauth/check_token");

// tokenServices.setAccessTokenConverter(accessTokenConverter());

// return tokenServices;

// }

@Bean

public AccessTokenConverter accessTokenConverter() {

return new DefaultAccessTokenConverter();

}

@Bean

RedisTokenStore redisTokenStore() {

return new RedisTokenStore(redisConnectionFactory);

}

// @Bean

// ClientDetailsService clientDetailsService() {

// return new JdbcClientDetailsService(dataSource);

// }

@Bean

@Primary

DefaultTokenServices defaultTokenServices() {

DefaultTokenServices tokenServices = new DefaultTokenServices();

tokenServices.setTokenStore(redisTokenStore());

// tokenServices.setSupportRefreshToken(true);

// tokenServices.setClientDetailsService(clientDetailsService());

// tokenServices.setAccessTokenValiditySeconds(60 * 60 * 12); // token有效期自定义设置,默认12小时

// tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);//默认30天,这里修改

return tokenServices;

}

}

AuthResourceConfig,作为资源授权模块来说,它更多的出现在业务模块工程中,做的是资源授权的操作,每一个微服务模块都会被当成一个资源来定义,而请求资源,则需要每次校验 access_token

,这个类可以出现在任意一个微服务工程中。

AuthServerConfig

@Configuration

@EnableAuthorizationServer

public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

@Autowired

RedisConnectionFactory redisConnectionFactory;

@Autowired

DataSource dataSource;

@Autowired

private AuthenticationManager authenticationManager;

@Autowired

private UserDetailsServiceImpl userServices;

@Bean

RedisTokenStore redisTokenStore() {

return new RedisTokenStore(redisConnectionFactory);

}

@Bean

ClientDetailsService clientDetailsService() {

return new JdbcClientDetailsService(dataSource);

}

@Bean

@Primary

DefaultTokenServices defaultTokenServices() {

DefaultTokenServices tokenServices = new DefaultTokenServices();

tokenServices.setTokenStore(redisTokenStore());

tokenServices.setSupportRefreshToken(true);

tokenServices.setClientDetailsService(clientDetailsService());

tokenServices.setAccessTokenValiditySeconds(60 * 60 * 12); // token有效期自定义设置,默认12小时

tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);//默认30天,这里修改

return tokenServices;

}

@Override

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

security.tokenKeyAccess("permitAll()");

security.checkTokenAccess("isAuthenticated()");

security.allowFormAuthenticationForClients();

}

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

clients.withClientDetails(clientDetailsService());

}

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

endpoints.tokenStore(redisTokenStore()).userDetailsService(userServices).authenticationManager(authenticationManager).tokenServices(defaultTokenServices());

}

}

认证授权,顾名思义,看到实现的代码也明白,做的是与 Mysql和Redis的交互,做到关键的用户登录信息处理,以及token的有效期定义。

WebSecurityConfig

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired

private UserDetailsServiceImpl userServices;

@Bean

PasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

}

@Override

@Bean

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.userDetailsService(userServices).passwordEncoder(passwordEncoder());

}

@Override

public void configure(WebSecurity web) throws Exception {

web.ignoring().antMatchers("/css/**", "/js/**", "/plugins/**", "/favicon.ico");

}

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable();

// http

// .authorizeRequests()

// .anyRequest().authenticated()

// .antMatchers("/oauth/**").permitAll()

// .and()

// .csrf().disable();

}

public static void main(String[] args) {

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

boolean matches = encoder.matches("123456", "$2a$10$cKRbR9IJktfmKmf/wShyo.5.J8IxO/7YVn8twuWFtvPgruAF8gtKq");

System.out.println(matches);

// System.out.println(encoder.encode("123456"));

}

}

UserServiceImpl

@Service

public class UserDetailsServiceImpl implements UserDetailsService {

// @Autowired

// private SysUserDao sysUserDao;

@Override

public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

// SysUser sysUser = sysUserDao.findByUserName(s);

//

// if (sysUser == null) {

// throw new UsernameNotFoundException("用户名或密码错误");

// }

return new User(s, "$2a$10$cKRbR9IJktfmKmf/wShyo.5.J8IxO/7YVn8twuWFtvPgruAF8gtKq", new HashSet<>());

}

}

由于目前还没有介绍到使用 SpringDataJPA 以及 MyBatils-Plus,这里我们先将用户密码写死 123456。

application.yaml

server:

port: 8081

spring:

redis:

host: yanzhenyidai.com

port: 6379

password: ****

datasource:

url: jdbc:mysql://yanzhenyidai.com:3306/oauth2?useUnicode=true&characterEncoding=utf-8

username: yanzhenyidai

password: password

druid:

driver-class-name: com.mysql.jdbc.Driver

main:

allow-bean-definition-overriding: true

cloud:

nacos:

discovery:

server-addr: yanzhenyidai.com:8848

application:

name: squid-oauth2

show-sql: true

logging:

config: classpath:logback.xml

level:

org:

springframework:

web: info

OAuthApplication

@SpringBootApplication

@EnableDiscoveryClient

@RestController

public class OAuthApplication {

public static void main(String[] args) {

SpringApplication.run(OAuthApplication.class, args);

}

@GetMapping("/test")

public String test() {

return "test";

}

@RequestMapping("/user")

public Principal principal(Principal principal) {

return principal;

}

}

一切完成后,我们启动服务,来进行测试,这个时候需要使用到 POSTMAN

Authorization 中的 Basic 为固定值,后续加密字符串为 scope+password 的Base64解密值。

总结

使用OAuth2可以帮助我们进行鉴权,也可以解决CSRF跨域,在选型到OAuth的时候,还担心它会很复杂,毕竟之前是深深的体会使用 SpringSecurity 的无奈。

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值