oauth2.0–基础–03–简单搭建认证服务器,资源服务器


代码文章

https://gitee.com/DanShenGuiZu/learnDemo/tree/master/auth2.0--learn/simple-auth2.0/oauth_parent
  • 1

1、整体代码

  1. 框架:spring sercurity+oauth2.0

1.1、代码结构

  1. oauth_parent:父工程
  2. oauth-authorizationServer:认证服务器
  3. oauth-ResourceServer:资源服务器

2、oauth_parent:父工程代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>oauth-learn</groupId><artifactId>oauth-parent</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging>
&lt;parent&gt;&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;&lt;version&gt;2.1.3.RELEASE&lt;/version&gt;
&lt;/parent&gt;&lt;properties&gt;&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;&lt;project.reporting.outputEncoding&gt;UTF-8&lt;/project.reporting.outputEncoding&gt;&lt;java.version&gt;1.8&lt;/java.version&gt;
&lt;/properties&gt;&lt;dependencyManagement&gt;&lt;dependencies&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;&lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;&lt;version&gt;Greenwich.RELEASE&lt;/version&gt;&lt;type&gt;pom&lt;/type&gt;&lt;scope&gt;import&lt;/scope&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;javax.servlet&lt;/groupId&gt;&lt;artifactId&gt;javax.servlet-api&lt;/artifactId&gt;&lt;version&gt;3.1.0&lt;/version&gt;&lt;scope&gt;provided&lt;/scope&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;javax.interceptor&lt;/groupId&gt;&lt;artifactId&gt;javax.interceptor-api&lt;/artifactId&gt;&lt;version&gt;1.2&lt;/version&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;com.alibaba&lt;/groupId&gt;&lt;artifactId&gt;fastjson&lt;/artifactId&gt;&lt;version&gt;1.2.47&lt;/version&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;&lt;artifactId&gt;lombok&lt;/artifactId&gt;&lt;version&gt;1.18.0&lt;/version&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;&lt;artifactId&gt;spring-security-jwt&lt;/artifactId&gt;&lt;version&gt;1.0.10.RELEASE&lt;/version&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.security.oauth.boot&lt;/groupId&gt;&lt;artifactId&gt;spring-security-oauth2-autoconfigure&lt;/artifactId&gt;&lt;version&gt;2.1.3.RELEASE&lt;/version&gt;&lt;/dependency&gt;&lt;/dependencies&gt;
&lt;/dependencyManagement&gt;&lt;build&gt;&lt;plugins&gt;&lt;plugin&gt;&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;&lt;configuration&gt;&lt;source&gt;1.8&lt;/source&gt;&lt;target&gt;1.8&lt;/target&gt;&lt;/configuration&gt;&lt;/plugin&gt;&lt;plugin&gt;&lt;artifactId&gt;maven-resources-plugin&lt;/artifactId&gt;&lt;configuration&gt;&lt;encoding&gt;utf-8&lt;/encoding&gt;&lt;useDefaultDelimiters&gt;true&lt;/useDefaultDelimiters&gt;&lt;/configuration&gt;&lt;/plugin&gt;&lt;/plugins&gt;
&lt;/build&gt;

</project>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

3、认证服务器代码:oauth-authorizationServer

3.1、代码

UserAuthorizeBean


package com.feizhou.oauth.bean;

import lombok.Data;

/**

  • 描述该类- JPA
  • @author zhoufei
  • @class: UserBean
  • @date 2020/10/27 16:09
  • @Verson 1.0 -2020/10/27 16:09
  • @see
    */

@Data
public class UserAuthorizeBean {
private Long id;
private Long userId;
private String authorizeCode;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

UserBean

package com.feizhou.oauth.bean;

import lombok.Data;

/**

  • 描述该类- JPA
  • @author zhoufei
  • @class: UserBean
  • @date 2020/10/27 16:09
  • @Verson 1.0 -2020/10/27 16:09
  • @see
    */

@Data
public class UserBean {
private Long id;
private String userName;
private String password;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

AuthorizationServer


package com.feizhou.oauth.config;

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.crypto.bcrypt.BCryptPasswordEncoder;
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.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

/**

  • 描述该类- JPA
  • @author zhoufei
  • @class: AuthorizationServer
  • @date 2020/10/28 21:26
  • @Verson 1.0 -2020/10/28 21:26
  • @see
    */

@Configuration
@EnableAuthorizationServer // 配置授权服务。
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

// 用来配置客户端详情服务
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {// 这里是第三方合作用户的客户id,秘钥的配置// 使用in-memory存储clients.inMemory()// client_id,用户账号.withClient("c1")// 客户端密钥.secret(new BCryptPasswordEncoder().encode("secret"))// 资源列表,资源标识.resourceIds("res1")// 授权类型(4种).authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit","refresh_token")// 客戶端允许的授权范围.scopes("all")// false跳转到授权页面,让用户点击授权,如果是true,相当于自动点击授权,就不跳转授权页面.autoApprove(false)//// 加上验证回调地址,返回授权码信息.redirectUris("http://www.baidu.com");// 如果有多个用户,配置多个客户详情// .and().withClient()}@Autowired
// 令牌存储策略
private TokenStore tokenStore;
@Autowired
// 客户端详情服务,也就是configure(ClientDetailsServiceConfigurer clients)方法
private ClientDetailsService clientDetailsService;// 令牌管理服务
@Bean
public AuthorizationServerTokenServices tokenService() {DefaultTokenServices service = new DefaultTokenServices();service.setClientDetailsService(clientDetailsService);service.setSupportRefreshToken(true);// 支持刷新service.setTokenStore(tokenStore);// 令牌存储service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天return service;
}@Autowired
// 授权码服务
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
// 认证管理
private AuthenticationManager authenticationManager;
@Autowired
// 令牌管理服务
private AuthorizationServerTokenServices authorizationServerTokenServices;@Override
// 用来配置令牌(token)的访问端点
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints// 密码模式需要.authenticationManager(authenticationManager)// 授权码模式需要.authorizationCodeServices(authorizationCodeServices)// 令牌管理服务.tokenServices(authorizationServerTokenServices).allowedTokenEndpointRequestMethods(HttpMethod.POST);// 允许post提交
}@Bean
// 授权码服务器
public AuthorizationCodeServices authorizationCodeServices() {// 授权码模式的授权码采用内存方式存储return new InMemoryAuthorizationCodeServices();
}@Override
// 用来配置令牌端点的安全约束,拦截规则
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security// 提供公有密匙的端点,如果你使用JWT令牌的话, 允许.tokenKeyAccess("permitAll()")// oauth/check_token:用于资源服务访问的令牌解析端点,允许.checkTokenAccess("permitAll()")// 表单认证,申请令牌.allowFormAuthenticationForClients();
}@Bean
// 令牌存储策略
public TokenStore tokenStore() {// 内存存储,普通令牌return new InMemoryTokenStore();
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

WebSecurityConfig


package com.feizhou.oauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**

  • @author Administrator

  • @version 1.0
    **/
    @Configuration
    @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    // 认证管理器
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
    }

    // 密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
    }

    // 安全拦截机制
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.
    csrf().disable().

             authorizeRequests().antMatchers("/admin/p1").hasAnyAuthority("p1").antMatchers("/user/p2").hasAnyAuthority("p2").antMatchers("/login*").permitAll().anyRequest().authenticated().and().formLogin();
    

    }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

UserDao


package com.feizhou.oauth.dao;

import java.util.ArrayList;
import java.util.List;

import com.feizhou.oauth.bean.UserAuthorizeBean;
import com.feizhou.oauth.bean.UserBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**

  • 描述该类- JPA
  • @author zhoufei
  • @class: UserBean
  • @date 2020/10/27 16:09
  • @Verson 1.0 -2020/10/27 16:09
  • @see
    */

@Repository
public class UserDao {
@Autowired
JdbcTemplate jdbcTemplate;

// 根据账号查询用户信息
public UserBean getUserByUsername(String username) {String sql = "select * from user where user_name = ?";// 连接数据库查询用户List&lt;UserBean&gt; list = jdbcTemplate.query(sql, new Object[] { username },new BeanPropertyRowMapper&lt;&gt;(UserBean.class));if (list != null &amp;&amp; list.size() == 1) {return list.get(0);}return null;
}// 根据用户id查询用户权限
public List&lt;String&gt; getAuthorize(Long userId) {String sql = "SELECT * FROM user_authorize WHERE user_id =?";List&lt;UserAuthorizeBean&gt; list = jdbcTemplate.query(sql, new Object[] { userId },new BeanPropertyRowMapper&lt;&gt;(UserAuthorizeBean.class));List&lt;String&gt; authorizes = new ArrayList&lt;&gt;();list.forEach(c -&gt; authorizes.add(c.getAuthorizeCode()));return authorizes;
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

SpringDataUserDetailsService


package com.feizhou.oauth.service;

import java.util.List;

import com.feizhou.oauth.bean.UserBean;
import com.feizhou.oauth.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**

  • @author Administrator

  • @version 1.0
    **/
    @Service
    public class SpringDataUserDetailsService implements UserDetailsService {

    @Autowired
    UserDao userDao;

    // 根据账号查询用户信息,
    // 通过@Service将SpringDataUserDetailsService注入容器,通过UserDetailsService接口表明该类的类型是UserDetailsService
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

     // 将来连接数据库根据账号查询用户信息UserBean bean = userDao.getUserByUsername(username);if (bean == null) {// 如果用户查不到,返回null,由provider来抛出异常return null;}// 查询当前数据库的用户资源权限List&lt;String&gt; authorize = userDao.getAuthorize(bean.getId());String[] authorizeArr = new String[authorize.size()];authorize.toArray(authorizeArr);// 添加权限UserDetails userDetails = User.withUsername(bean.getUserName()).password(bean.getPassword()).authorities(authorizeArr).build();return userDetails;
    

    }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

application.properties


spring.application.name=oauth-authorizationServer
server.port=8081

spring.datasource.url = jdbc:mysql://zhoufei.ali.db.com:3306/test?useUnicode=true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name = com.mysql.jdbc.Driver

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

pom.xml


<?xml version=“1.0” encoding=“UTF-8”?>
<project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<parent>
<artifactId>oauth-parent</artifactId>
<groupId>oauth-learn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

&lt;artifactId&gt;oauth-authorizationServer&lt;/artifactId&gt;&lt;dependencies&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.data&lt;/groupId&gt;&lt;artifactId&gt;spring-data-commons&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;&lt;artifactId&gt;spring-cloud-starter-security&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;&lt;artifactId&gt;spring-cloud-starter-oauth2&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;&lt;artifactId&gt;spring-security-jwt&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;mysql&lt;/groupId&gt;&lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;&lt;artifactId&gt;spring-boot-starter-jdbc&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;&lt;artifactId&gt;lombok&lt;/artifactId&gt;&lt;/dependency&gt;&lt;/dependencies&gt;

</project>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

mysql.sql

数据库脚本


CREATE TABLE `user` (`id` bigint(255) NOT NULL AUTO_INCREMENT,`password` varchar(255) DEFAULT NULL,`user_name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

CREATE TABLE user_authorize (
id bigint(20) NOT NULL AUTO_INCREMENT,
user_id bigint(20) DEFAULT NULL,
authorize_code varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

INSERT INTO user_authorize(id, user_id, authorize_code) VALUES (1, 1, ‘admin’);
– 账号密码都是admin
INSERT INTO user(id, password, user_name) VALUES (1, ‘$2a$10$4ewqeeIzvg4rBIIvSC4QFu4DEO0xGcHetdjac4950UbOX91Jrk1we’, ‘admin’);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3.2、解读代码

3.2.1、OAuth2.0授权服务器的开启

  1. 使用 @EnableAuthorizationServer注解
  2. 继承 AuthorizationServerConfigurerAdapter

3.2.2、AuthorizationServerConfigurerAdapter:

要配置以下几个类,通过重写以下方法来实现

3.2.3、ClientDetailsServiceConfigurer

  1. 用来配置客户端详情服务(ClientDetailsService)

    1. ClientDetailsService负责查找ClientDetails
  2. 客户端详情服务:第三方服务器来授权服务器申请访问资源。通过授权后,颁发clientId,secret给第三方服务器,表示第三方服务器是信任的服务器。
  3. 可通过内存或者数据库来配置

ClientDetails重要属性列表:

  1. clientId:标识客户的Id
  2. secret:客户端秘钥
  3. scope:
    1. 限制客户端的访问范围
    2. 默认空:拥有全部的访问范围。
  4. authorizedGrantTypes:
    1. 客户端可以使用的授权类型
    2. 默认为空
  5. authorities:
    1. 客户端可以使用的权限
    2. 基于SpringSecurityauthorities

ClientDetails介绍

  1. 能够在应用程序运行的时候进行更新
  2. 可以通过访问底层的存储服务
    1. 客户端详情存储在一个关系数据库的表中
    2. 实现方式
      1. 使用JdbcClientDetailsService
      2. 自己实现ClientRegistrationService接口
      3. 自己实现ClientDetailsService接口

具体代码

3.2.4、AuthorizationServerTokenServices

  1. 令牌管理服务
  2. 定义管理令牌的操作
  3. 令牌
    1. 用来加载身份信息
    2. 包含了这个令牌的相关权限。
  4. 这个接口的实现,则需要继承DefaultTokenServices

DefaultTokenServices

  1. 可以修改令牌的格式
  2. 可以修改令牌的存储。
  3. 默认:创建一个令牌使用随机值来进行填充的
  4. 除了持久化令牌是委托一个TokenStore接口来实现以外,这个类几乎帮你做了所有的事情。

TokenStore

  1. 默认实现:InMemoryTokenStore

    1. 所有的令牌是被保存在了内存中
    2. 它可以完美的工作在单服务器上(即访问并发量压力不大的情况下,并且它在失败的时候不会进行备份)
  2. JdbcTokenStore
    1. 基于JDBC的实现版本,令牌会被保存进关系型数据库
    2. 注意点:需要把"spring-jdbc"这个依赖加入到你的classpath当中。
  3. JwtTokenStore
    1. 它可以把令牌相关的数据进行编码(因此对于后端服务来说,它不需要进行存储,这将是一个重大优势)
    2. 缺点:
      1. 撤销一个已经授权令牌非常困难,所以它通常用来处理一个生命周期较短的令牌以及撤销刷新令牌(refresh_token)
      2. 这个令牌占用的空间会比较大,如果你加入了比较多用户凭证信息。JwtTokenStore不会保存任何数据,但是它在转换令牌值以及授权信息方面与DefaultTokenServices所扮演的角色是一样的。

3.2.5、AuthorizationServerEndpointsConfigurer

  1. 可以完成令牌服务
  2. 可以完成令牌endpoint配置

配置授权类型(GrantTypes)

  1. authenticationManager:认证管理器

    1. 选择密码(password)授权类型的时候,请设置这个属性注入一个AuthenticationManager对象。
  2. userDetailsService:
    1. 设置UserDetailsService接口的实现类(用户登录验证)
    2. 可以把这个东西设置到全局域上面去(例如GlobalAuthenticationManagerConfigurer这个配置对象),当你设置了这个之后,那么"refresh_token"即刷新令牌授权类型模式的流程中就会包含一个检查,用来确保这个账号是否仍然有效。
  3. authorizationCodeServices:设置授权码服务
    1. 用于"authorization_code"授权码类型模式
  4. implicitGrantService:设置隐式授权模式,用来管理隐式授权模式的状态。
  5. tokenGranter:
    1. 设置TokenGranter接口实现,授权将会交由你来完全掌控,并且会忽略掉上面的这几个属性
    2. 这个属性一般是用作拓展用途的,即标准的四种授权模式已经满足不了你的需求的时候,才会考虑使用这个。

具体代码

配置授权端点的URL(EndpointURLs)

  1. AuthorizationServerEndpointsConfigurer有一个pathMapping()的方法用来配置端点URL链接
  2. 它有两个参数
    1. 第一个参数:String类型的,这个端点URL的默认链接。
    2. 第二个参数:String类型的,你要进行替代的URL链接。
    3. 以上的参数都将以"/"字符为开始的字符串,
    4. 框架的默认URL链接如下列表,可以作为这个pathMapping()方法的第一个参数
      1. /oauth/authorize:授权端点。
      2. /oauth/token:令牌端点。
      3. /oauth/confirm_access:用户确认授权提交端点。
      4. /oauth/error:授权服务错误信息端点。
      5. /oauth/check_token:用于资源服务访问的令牌解析端点。
      6. /oauth/token_key:提供公有密匙的端点,如果你使用JWT令牌的话。需要注意的是授权端点这个URL应该被SpringSecurity保护起来只供授权用户访问。

3.2.6、authorizationCodeServices

授权码服务的存储方式

具体代码


3.2.7、AuthorizationServerSecurityConfigurer

  1. 令牌端点的安全约束
  2. tokenkey:/oauth/token_key端点完全公开。
  3. checkToken:/oauth/check_token端点完全公开。
  4. allowFormAuthenticationForClients:允许表单认证

具体代码

3.3、验证认证服务器

3.3.1、授权码模式

01、请求授权码

http://localhost:8081/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
  • 1

02、先让你登录(Security的原因)

02、用户授权

03、返回授权码

04、请求taken

http://localhost:8081/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=kZAlHW&redirect_uri=http://www.baidu.com
  • 1

3.3.2、简化模式

http://localhost:8081/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com
  • 1

3.3.3、密码模式

http://localhost:8081/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=admin&password=admin
  • 1

3.3.4、客户端模式


http://localhost:8081/oauth/token?client_id=c1&client_secret=secret&grant_type=client_credentials
  • 1
  • 2

4、资源服务器代码:oauth-ResourceServer

4.1、代码

ResouceServerConfig

package com.feizhou.oauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;

/**

  • @author Administrator

  • @version 1.0
    **/
    @Configuration
    @EnableResourceServer
    public class ResouceServerConfig extends ResourceServerConfigurerAdapter {

    // 授权服务的资源列表
    public static final String RESOURCE_ID = “res1”;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
    resources
    // 资源 id
    .resourceId(RESOURCE_ID)
    // 令牌服务
    .tokenServices(tokenService())
    .stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {

     http.authorizeRequests().antMatchers("/**")// 所有的访问,授权访问都要是all,和认证服务器的授权范围一一对应.access("#oauth2.hasScope('all')")//去掉防跨域攻击.and().csrf().disable()//session管理.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    

    }

    @Bean
    // 资源服务令牌解析服务
    public ResourceServerTokenServices tokenService() {
    // 使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
    RemoteTokenServices service = new RemoteTokenServices();
    service.setCheckTokenEndpointUrl(“http://localhost:8081/oauth/check_token”);
    service.setClientId(“c1”);
    service.setClientSecret(“secret”);
    return service;
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

ResouceServerConfig

package com.feizhou.oauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

//由于Spring boot starter自动装配机制,这里无需使用@EnableWebSecurity
//@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 方法授权
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

// 密码编码器,不加密
@Bean
public PasswordEncoder passwordEncoder() {// return NoOpPasswordEncoder.getInstance(); // 不加密return new BCryptPasswordEncoder();// BCryptPasswordEncoder加密
}// web url 拦截规则
@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated()// 所有其他请求必须认证通过.and().formLogin().loginPage("/login").successForwardUrl("/login-success")// 自定义登录成功的页面地址.permitAll().and().logout().permitAll().and()// 会话管理.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);// 会话管理
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

LoginController


package com.feizhou.oauth.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**

  • @author Administrator

  • @version 1.0
    **/
    @RestController
    public class LoginController {

    @RequestMapping(value = “/login-success”)
    public String loginSuccess() {
    return getUsername() + " login-success 登录成功";
    }

    /**

    • 测试资源1
    • @return
      */
      @GetMapping(value = “/admin/p1”)
      @PreAuthorize(“hasAuthority(‘p1’)”)//拥有p1权限才可以访问
      public String r1() {
      return " /admin/p1 " + getUsername() + “访问资源1”;
      }

    /**

    • 测试资源2
    • @return
      */
      @GetMapping(value = “/user/p2”)
      @PreAuthorize(“hasAuthority(‘p2’)”)//拥有p2权限才可以访问
      public String r2() {
      return "/user/p2 " + getUsername() + “访问资源2”;
      }

    // 获取当前用户信息
    private String getUsername() {
    String username = null;
    // 当前认证通过的用户身份
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    // 用户身份
    Object principal = authentication.getPrincipal();
    if (principal == null) {
    username = “匿名”;
    }
    if (principal instanceof UserDetails) {
    UserDetails userDetails = (UserDetails) principal;
    username = userDetails.getUsername();
    } else {
    username = principal.toString();
    }
    return username;
    }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

application.properties


spring.application.name=oauth-ResourceServer
server.port=8082
  • 1
  • 2
  • 3

pom.xml


<?xml version=“1.0” encoding=“UTF-8”?>
<project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<parent>
<artifactId>oauth-parent</artifactId>
<groupId>oauth-learn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

&lt;artifactId&gt;oauth-ResourceServer&lt;/artifactId&gt;&lt;dependencies&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;&lt;artifactId&gt;spring-cloud-starter-security&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;&lt;artifactId&gt;spring-cloud-starter-oauth2&lt;/artifactId&gt;&lt;/dependency&gt;&lt;dependency&gt;&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;&lt;artifactId&gt;lombok&lt;/artifactId&gt;&lt;/dependency&gt;&lt;/dependencies&gt;

</project>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

4.2、代码解读

4.2.1、OAuth2.0资源服务器的开启

  1. 需要添加 @EnableResourceServer注解

    1. 会自动增加了一个类型为 OAuth2AuthenticationProcessingFilter 的过滤器链
  2. 需要 继承ResourceServerConfigurerAdapter

4.2.2、ResourceServerSecurityConfigurer

  1. tokenServices:

    1. ResourceServerTokenServices 类的实例
    2. 用来实现令牌服务
  2. tokenStore:
    1. TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选
  3. resourceId
    1. 这个资源服务的ID,这个属性是可选的,推荐设置并在授权服务中进行验
  4. tokenExtractor
    1. 令牌提取器用来提取请求中的令牌

4.2.3、HttpSecurity配置这个与Spring Security类似

4.2.4、ResourceServerTokenServices

  1. DefaultTokenServices

    1. 授权服务和资源服务在同一个应用程序上可以使用
    2. 在资源服务器本地配置令牌存储、解码、解析方式使用
  2. RemoteTokenServices
    1. 资源服务器通过HTTP请求来解码令牌
    2. 请求端点:/oauth/check_token

4.3、测试

01、获取token

02、检查token的信息

03、admin请求可以访问的资源

04、user请求可以访问的资源(token 是admin的)

认证服务器,资源服务器相关推荐

  1. 扩展资源服务器解决oauth2 性能瓶颈

    用户携带token 请求资源服务器 资源服务器拦截器 携带token 去认证服务器 调用tokenstore 对token 合法性校验 资源服务器拿到token,默认只会含有用户名信息 通过用户名调用 ...

  2. 认证服务器的搭建_SpringCloud搭建的认证中心和资源服务器的微服务项目源码分享...

    本项目基于spring-cloud-starter-oauth2搭建的认证中心和资源服务器的微服务项目,项目不仅仅简单的demo,项目的出发点在于实战应用.本项目为笔者花了不少时间和精力整理出来的,只 ...

  3. Spring Security 0auth2 认证服务器和资源服务器实现

    一,OAuth2开放授权协议/标准 OAuth(开放授权)是⼀个开放协议/标准,允许⽤户授权第三⽅应⽤访问他们存储在另外的服务提供者 上的信息,⽽不需要将⽤户名和密码提供给第三⽅应⽤或分享他们数据的所 ...

  4. 使用Spring Security 资源服务器来保护Spring Cloud 微服务

    我在上一篇对资源服务器进行了简单的阐述,让大家对资源服务器的概念有了简单的认识,今天我将用实际例子来演示单体应用改造为Spring Cloud微服务时的资源服务器实现. 资源服务器改造 以Spring ...

  5. Apsara Clouder云计算专项技能认证:云服务器ECS入门[考试真题]

    Apsara Clouder云计算专项技能认证:云服务器ECS入门[认证考试真题](答案仅供参考) 单选题13题 开放云服务器ECS安全组里22端口,有什么作用? A.可以远程访问数据库 B.支持ht ...

  6. 使用Spring Security Oauth2 和 JWT保护微服务--资源服务器的编写

    编写hcnet-website的资源服务 依赖管理pom文件 hcnet-website工程的pom文件继承主maven的pom文件.在hcnet-website工程的pom文件中添加web功能的起步 ...

  7. 2023阿里云学生服务器权益,含Clouder认证:云服务器ECS答案

    文章目录 阿里云学生权益(服务器使用7个月) 1.高校计划续费任务 - 飞天加速计划3.0(2个任务) 2.任务1:完成实验<ECS云服务器新手上路> 2.2: 续费6个月 3.任务2:A ...

  8. Tomcat 动态资源服务器部署及应用

    Tomcat 动态资源服务器部署及应用 Java 2 EE 计数体系包含如 Serverlet , JSP , JMX 等等. 以OpenJDK为例,当前比较常用的有1.6.0.1.7.0.1.8.0 ...

  9. SpringSecurity(二十)---OAuth2:实现资源服务器(上)资源服务器搭建以及直接调用授权服务器模式

    一. 前言 本章将讨论如何使用Spring Security实现一个资源服务器,资源服务器是管理用户资源的组件.另外,学习本章有个前提,需要先把前面搭建授权服务器的相关文章先给阅读,否则可能后面出现的 ...

最新文章

  1. LTE QCI分类 QoS
  2. 软件测试培训适合什么人学习?
  3. ASIC设计的一些软件
  4. 互联网共鸣之声:2018年或成为云计算转折之年
  5. windowswps怎么以文件形式发送_一个招投标项目出现了履约争议,但是没有签订合同,怎么办?...
  6. 响应json数据之过滤静态资源
  7. dj鲜生-25-用户登陆验证成功-但是没有激活的处理
  8. 搜索引擎的强大意味着与之合作就会双赢?
  9. [Windows] 程序生成出现语法错误: 意外的令牌“标识符”,预期的令牌为“类型说明符”...
  10. win11快捷键失效怎么处理 Windows快捷键失效的解决方法
  11. Python文档学习笔记(1)--使用Python 解释器
  12. 如何对散列查找进行asl分析计算?_Python数据结构与算法——散列(Hash)
  13. 各种注册序列号 用户名
  14. Tomcat9一介绍与部署
  15. 柳州铁一中机器人_柳州铁路第一中学的办学成果
  16. 训练记录番外篇(2):2022 ICPC Gran Premio de Mexico 2da Fecha
  17. recycler上下拉刷新view
  18. java-net-php-python-jspm现代化社区去也管理系统计算机毕业设计程序
  19. 脱粉之后,华为的喜忧参半
  20. 这么多编程学习网站,总有一个适合你吧

热门文章

  1. 14个上级与下属进行绩效面谈时的主题(四)
  2. Wdf框架之WdfObject状态机(2) 一文再补充
  3. 【傅老师DarkSouls第一季】04
  4. 智商不高怎么办才好?
  5. 《我的视频我做主:Premiere Pro CS5实战精粹》——导读
  6. c#+dev-ComboboxEdit控件用法
  7. 2022年充电宝品牌排行榜,2022年充电宝推荐
  8. 《IT经理世界》封面报道:淘宝隐忧3
  9. 不会找对象?教你两招再试试【适用于Java攻城狮】
  10. IaaS、PaaS、SaaS、BaaS、FaaS区别