spring cloud之oauth2

首先我们在了解oath2授权认证时,需要先了解Security认证,同时Security认证也是有许多种认证方式的我们这边主要学习数据库认证啦,首先我们需要三张表用户表,角色表,用户角色表。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
同时需要在pom中导入Security:

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-security</artifactId>
		</dependency>

接下来我们就可以去实现Security认证啦,首先创建一个WebSecurityConfiguration类继承WebSecurityConfigurerAdapter,我就直接贴代码啦:

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private DomainUserDetailsService userDetailsService;

    // 配置认证(用户名密码认证)
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new SCryptPasswordEncoder());
    }

    //配置授权(资源的访问规则)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //允许跨域访问
        http.csrf().disable();
        //允许直接访问
        http.authorizeRequests().antMatchers("/login").permitAll();
        //允许基于HttpServletRequest使用
        http.authorizeRequests()
                //对于/admin/** 只有ADMIN角色可以访问
                .antMatchers("/admin/**")
                .hasRole("ADMIN");
        http.authorizeRequests()
                //对于/test/** 只有ADMIN角色可以访问
                .antMatchers("/test/**")
                .hasRole("SUPER_ADMIN");
        http.authorizeRequests()
                //对于/user/** 只有USER角色可以访问
                .antMatchers("/user/**")
                .hasRole("USER");
        http.authorizeRequests()
                //对于/combination/** 同时具有两个角色才可以访问
                .antMatchers("/combination/**")
                .access("hasRole('ADMIN') and hasRole('USER')");
        //对于没有匹配上的路径, 则需要认证, 不区分角色
//        http.authorizeRequests().anyRequest().authenticated();
        // 表单登录认证(通过浏览器访问的时候回跳转到/login登录页),如果不配置,则浏弹出览器自带的登录框
        http.formLogin();
        // httpbasic认证(通过postman访问时), 如果不配置则自动跳到登录页
        http.httpBasic();
    }
}

那么我们继续看看service是怎么实现的:

@Service
public class DomainUserDetailsService implements UserDetailsService {
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Map<String, Object> userPo = jdbcTemplate.queryForMap("select * from auth_user where username='" + username + "'");
        if (userPo == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        Integer id = (Integer) userPo.get("id");
        String password = (String) userPo.get("password");
        //用户权限
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT r.`role_name` FROM auth_user_role u INNER JOIN auth_role r ON u.`role_id` = r.`id`  WHERE u.user_id=" + id);
        if (!CollectionUtils.isEmpty(list)) {
            for (Map<String, Object> po : list) {
                String roleCode = (String) po.get("role_name");
                authorities.add(new SimpleGrantedAuthority(roleCode));
            }
        }
        return new User(username, password, authorities);
    }
}

这样整个Security认证算是完成了,接下来你们可以写几个controller进行测试啦!!!下面我们开始说oauth2授权啦:

oauth2授权应该是现在用的最为广泛的授权模式了吧,首先我们来了解一下他的授权原理吧
在这里插入图片描述
可能不是特别理解吧,接下来我们进入代码实现会比较清晰一点吧:
在pom配置oauth2所需jar包:

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-oauth2</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

配置yml文件:

#服务器配置
server:
  #端口
  port: 9060

#服务器发现注册配置
eureka:
  client:
    serviceUrl:
      #配置服务中心(可配置多个,用逗号隔开)
        defaultZone: http://localhost:9010/eureka
#spring配置
spring:
  #应用配置
  application:
    #名称: OAuth2认证授权服务
    name: service-oauth
  #数据库配置
  datasource:
    druid:
      # 数据库连接驱动
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: 123
      filters: stat
      max-active: 20
      initial-size: 1
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 1
      test-while-idle: true
      test-on-borrow: true
      test-on-return: true
      pool-prepared-statements: true
      max-open-prepared-statements: 20
  # redis配置
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
  jmx:
    default-domain: service-oauth
# 打印sql
logging:
  level:
    com.ctkj.oauth.mapper : debug

认证服务器配:

package com.ctkj.oauth.config;

import com.ctkj.oauth.service.impl.DomainUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.sql.DataSource;

/**
 * 认证服务器配置
 */
@Configuration
@EnableAuthorizationServer
public   class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Autowired
    DomainUserDetailsService domainUserDetailsService;

    @Autowired
    private DataSource dataSource;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetails());
        //authorization_code模式测试地址:
        //  第一步获取code(GET):  http://localhost:9060/oauth/authorize?client_id=client&response_type=code&scope=select&redirect_uri=www.baidu.com
        //  第二部获取token(POST): http://localhost:9060/oauth/token?grant_type=authorization_code&code=I2LK5r&client_id=client&client_secret=123456&redirect_uri=http://tets98y.com
        //password模式测试地址(POST):http://localhost:9060/oauth/token?username=admin&password=123456&grant_type=password&scope=select&client_id=client&client_secret=123456

    }
    @Bean
    public ClientDetailsService clientDetails() {
        return new JdbcClientDetailsService(dataSource);
    }




    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //token放入redis中,进行存储
        endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
                .authenticationManager(authenticationManager)
                .userDetailsService(domainUserDetailsService);

    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                //url:/oauth/token_key,exposes public key for token verification if using JWT tokens
                .tokenKeyAccess("permitAll()")
                //url:/oauth/check_token allow check token
                .checkTokenAccess("isAuthenticated()")
                //允许表单认证
                .allowFormAuthenticationForClients();
    }

}

资源服务:

package com.ctkj.oauth.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.http.HttpServletRequest;

/**
 * 配置资源服务器
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {


    @Override
    public void configure(HttpSecurity http) throws Exception {
        //允许基于HttpServletRequest使用
//        http.authorizeRequests()
//                //对于/oauth/any/** 赋予任何人都可以访问的权限
//                .antMatchers("/oauth/any/**").permitAll();
        http.authorizeRequests()
                //对于/oauth/admin/** 只有ADMIN角色可以访问
                .antMatchers(HttpMethod.GET, "/admin/**")
                .hasRole("ADMIN");
        http.authorizeRequests()
                //对于/oauth/user/** 只有USER角色可以访问
                .antMatchers("/user/**")
                .hasRole("USER");
        http.authorizeRequests()
                //对于/oauth/both/** 同时具有两个角色才可以访问
                .antMatchers("test/**")
                .access("hasRole('ADMIN') and hasRole('USER')");
    }

}

授权服务器

package com.ctkj.oauth.config;

import com.ctkj.oauth.service.impl.DomainUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private DomainUserDetailsService userDetailsService;

//     配置认证(用户名密码认证)
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new SCryptPasswordEncoder());
    }

    //配置授权(资源的访问规则)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //允许跨域访问
        http.csrf().disable();
        http.cors().disable();
        http.authorizeRequests().antMatchers("/oauth/**","/login").permitAll();
        //对于没有匹配上的路径, 则需要认证, 不区分角色
        http.authorizeRequests().anyRequest().authenticated();
        // httpbasic认证(通过postman访问时),如果不配置则自动跳到登录页
        http.httpBasic();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager manager = super.authenticationManagerBean();
        return manager;
    }

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

同时还需要在加一张表:客户端授权表:
在这里插入图片描述

这样算配好啦,oauth2授权模式有4种,这边我只做两种授权模式的一个测试啦,接下来咱们一起走一遍测试吧:
授权码模式:
第一步获取code:
http://localhost:9060/oauth/authorize?client_id=web&response_type=code&scope=web&redirect_uri=www.iuyr.com该链接的参数对于数据库字段中的value值就好了。response_type授权类型我们设置为code就可以了。
第二步我们会进入一个登陆页面
在这里插入图片描述
登陆成功后会返回一串地址该地址是你设置的地址后面的code就是用来获取token的:
在这里插入图片描述
第三步通过code获取token,我们采用postman去获取:在这里插入图片描述
这样整体授权码模式就完成了!!!快去试试用token访问不同的地址看看效果吧!

第二种授权模式:password授权这个也是我们最常用的授权模式:
第一步直接访问:
在这里插入图片描述
在这里插入图片描述
这样你就可以拿到token了,然后可以开始测试了!!!!
这样最简单的一个授权认证模块就算完成啦

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戴~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值