用戶登陸
時間:2023-05-20 03:30:01 | 來源:網(wǎng)站運營
時間:2023-05-20 03:30:01 來源:網(wǎng)站運營
用戶登陸:if年少有為
業(yè)精于勤,荒于嬉,行成于思,毀于隨。 -- 韓愈
springboot和springsecurity整合OAuth2
1. OAuth2.0介紹OAuth
(開放授權(quán))是一個開放標(biāo)準(zhǔn),允許用戶授權(quán)第三方應(yīng)用訪問他們存儲在另外的服務(wù)提供者上的信息,而不需要將用戶名和密碼提供給第三方應(yīng)用或分享他們數(shù)據(jù)的所有內(nèi)容。
OAuth2.0
是
OAuth
協(xié)議的延續(xù)版本,但不向后兼容
OAuth 1.0
即完全廢止了
OAuth1.0
。很多大公司如
Google
,
Yahoo
,
Microsoft
等都提供了
OAUTH
認證服務(wù),這些都足以說明
OAUTH
標(biāo)準(zhǔn)逐漸成為開放資源授權(quán)的標(biāo)準(zhǔn)。
Oauth
協(xié)議目前發(fā)展到2.0版本,1.0版本過于復(fù)雜,2.0版本已得到廣泛應(yīng)用。
下邊分析一個
Oauth2
認證的例子,通過例子去理解
OAuth2.0
協(xié)議的認證流程,本例子是黑馬程序員網(wǎng)站使用微信認證的過程,這個過程的簡要描述如下:
用戶借助微信認證登錄黑馬程序員網(wǎng)站,用戶就不用單獨在黑馬程序員注冊用戶,怎么樣算認證成功嗎?黑馬程序
員網(wǎng)站需要成功從微信獲取用戶的身份信息則認為用戶認證成功,那如何從微信獲取用戶的身份信息?用戶信息的
擁有者是用戶本人,微信需要經(jīng)過用戶的同意方可為黑馬程序員網(wǎng)站生成令牌,黑馬程序員網(wǎng)站拿此令牌方可從微
信獲取用戶的信息。
- 1、 客戶端請求第三方授權(quán)
用戶進入黑馬程序的登錄頁面,點擊微信的圖標(biāo)以微信賬號登錄系統(tǒng),用戶是自己在微信里信息的資源擁有者。
點擊“微信”出現(xiàn)一個二維碼,此時用戶掃描二維碼,開始給黑馬程序員授權(quán)。 - 2、 資源擁有者同意給客戶端授權(quán)
資源擁有者掃描二維碼表示資源擁有者同意給客戶端授權(quán),微信會對資源擁有者的身份進行驗證, 驗證通過后,微信會詢問用戶是否給授權(quán)黑馬程序員訪問自己的微信數(shù)據(jù),用戶點擊“確認登錄”表示同意授權(quán),微信認證服務(wù)器會頒發(fā)一個授權(quán)碼,并重定向到黑馬程序員的網(wǎng)站。 - 3、 客戶端獲取到授權(quán)碼,請求認證服務(wù)器申請令牌
此過程用戶看不到,客戶端應(yīng)用程序請求認證服務(wù)器,請求攜帶授權(quán)碼。 - 4、認證服務(wù)器向客戶端響應(yīng)令牌
微信認證服務(wù)器驗證了客戶端請求的授權(quán)碼,如果合法則給客戶端頒發(fā)令牌,令牌是客戶端訪問資源的通行證。
此交互過程用戶看不到,當(dāng)客戶端拿到令牌后,用戶在黑馬程序員看到已經(jīng)登錄成功。 - 5、客戶端請求資源服務(wù)器的資源
客戶端攜帶令牌訪問資源服務(wù)器的資源。
黑馬程序員網(wǎng)站攜帶令牌請求訪問微信服務(wù)器獲取用戶的基本信息。 - 6、資源服務(wù)器返回受保護資源
資源服務(wù)器校驗令牌的合法性,如果合法則向用戶響應(yīng)資源信息內(nèi)容。
以上認證授權(quán)詳細的執(zhí)行流程如下:OAuth2.0認證流程:OAauth2.0包括以下角色:1、客戶端本身不存儲資源,需要通過資源擁有者的授權(quán)去請求資源服務(wù)器的資源,比如:
Android
客戶端、
Web
客戶端(瀏覽器端)、微信客戶端等。
2、資源擁有者通常為用戶,也可以是應(yīng)用程序,即該資源的擁有者。
3、授權(quán)服務(wù)器(也稱認證服務(wù)器)用于服務(wù)提供商對資源擁有的身份進行認證、對訪問資源進行授權(quán),認證成功后會給客戶端發(fā)放令牌
(
access_token
),作為客戶端訪問資源服務(wù)器的憑據(jù)。本例為微信的認證服務(wù)器。
4、資源服務(wù)器存儲資源的服務(wù)器,本例子為微信存儲的用戶信息。
現(xiàn)在還有一個問題,服務(wù)提供商能允許隨便一個客戶端就接入到它的授權(quán)服務(wù)器嗎?答案是否定的,服務(wù)提供商會
給準(zhǔn)入的接入方一個身份,用于接入時的憑據(jù):
client_id
:客戶端標(biāo)識
client_secret
:客戶端秘鑰
因此,準(zhǔn)確來說,授權(quán)服務(wù)器對兩種
OAuth2.0
中的兩個角色進行認證授權(quán),分別是資源擁有者、客戶端。
2. OAuth2.0 中四種授權(quán)方式1. 授權(quán)碼模式( authorization code)流程說明:【A服務(wù)客戶端】需要用到【B服務(wù)資源服務(wù)】中的資源
第一步:【A服務(wù)客戶端】將用戶自動導(dǎo)航到【B服務(wù)認證服務(wù)】,這一步用戶需要提供一個回調(diào)地址,以備【B服務(wù)認證服務(wù)】返回授權(quán)碼使用。
第二步:用戶點擊授權(quán)按鈕表示讓【A服務(wù)客戶端】使用【B服務(wù)資源服務(wù)】,這一步需要用戶登錄B服務(wù),也就是說用戶要事先具有B服務(wù)的使用權(quán)限。
第三步:【B服務(wù)認證服務(wù)】生成授權(quán)碼,授權(quán)碼將通過第一步提供的回調(diào)地址,返回給【A服務(wù)客戶端】。
注意這個授權(quán)碼并非通行【B服務(wù)資源服務(wù)】的通行憑證。
第四步:【A服務(wù)認證服務(wù)】攜帶上一步得到的授權(quán)碼向【B服務(wù)認證服務(wù)】發(fā)送請求,獲取通行憑證
token
。
第五步:【B服務(wù)認證服務(wù)】給【A服務(wù)認證服務(wù)】返回令牌
token
和更新令牌
refresh token
。
使用場景授權(quán)碼模式是
OAuth2
中最安全最完善的一種模式,應(yīng)用場景最廣泛,可以實現(xiàn)服務(wù)之間的調(diào)用,常見的微信,QQ等第三方登錄也可采用這種方式實現(xiàn)。
2. 簡化模式(implicit)流程說明:簡化模式中沒有【A服務(wù)認證服務(wù)】這一部分,全部有【A服務(wù)客戶端】與B服務(wù)交互,整個過程不再有授權(quán)碼,token直接暴露在瀏覽器。
第一步:【A服務(wù)客戶端】將用戶自動導(dǎo)航到【B服務(wù)認證服務(wù)】,這一步用戶需要提供一個回調(diào)地址,以備【B服務(wù)認證服務(wù)】返回
token
使用,還會攜帶一個【A服務(wù)客戶端】的狀態(tài)標(biāo)識
state
。
第二步:用戶點擊授權(quán)按鈕表示讓【A服務(wù)客戶端】使用【B服務(wù)資源服務(wù)】,這一步需要用戶登錄B服務(wù),也就是說用戶要事先具有B服務(wù)的使用權(quán)限。
第三步:【 B服務(wù)認證服務(wù)】生成通行令牌
token
,
token
將通過第一步提供的回調(diào)地址,返回給【A服務(wù)客戶端】。
使用場景適用于A服務(wù)沒有服務(wù)器的情況。比如:純手機小程序,
JavaScript
語言實現(xiàn)的網(wǎng)頁插件等。
3. 密碼模式(resource owner password credentials)流程第一步:直接告訴【A服務(wù)客戶端】自己的【B服務(wù)認證服務(wù)】的用戶名和密碼
第二步:【A服務(wù)客戶端】攜帶【B服務(wù)認證服務(wù)】的用戶名和密碼向【B服務(wù)認證服務(wù)】發(fā)起請求獲取
token
。
第三步:【B服務(wù)認證服務(wù)】給【A服務(wù)客戶端】頒發(fā)
token
。
使用場景此種模式雖然簡單,但是用戶將B服務(wù)的用戶名和密碼暴露給了A服務(wù),需要兩個服務(wù)信任度非常高才能使
用。
4. 客戶端模式(client credentials)流程說明:這種模式其實已經(jīng)不太屬于
OAuth2
的范疇了。A服務(wù)完全脫離用戶,以自己的身份去向B服務(wù)索取
token
。換言之,用戶無需具備B服務(wù)的使用權(quán)也可以。完全是A服務(wù)與B服務(wù)內(nèi)部的交互,與用戶無關(guān)了。
第一步:A服務(wù)向B服務(wù)索取
token
。
第二步:B服務(wù)返回
token
給A服務(wù)。
使用場景A服務(wù)本身需要B服務(wù)資源,與用戶無關(guān)。
3. OAuth2.0 sql語句說明既可以寫死在代碼中,也可以寫入到數(shù)據(jù)庫中,通常寫入到數(shù)據(jù)庫
建表語句官方SQL地址:
sql
create table oauth_client_details ( client_id VARCHAR(256) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256) ); create table oauth_client_token ( token_id VARCHAR(256), token LONGVARBINARY, authentication_id VARCHAR(256) PRIMARY KEY, user_name VARCHAR(256), client_id VARCHAR(256) ); create table oauth_access_token ( token_id VARCHAR(256), token LONGVARBINARY, authentication_id VARCHAR(256) PRIMARY KEY, user_name VARCHAR(256), client_id VARCHAR(256), authentication LONGVARBINARY, refresh_token VARCHAR(256) ); create table oauth_refresh_token ( token_id VARCHAR(256), token LONGVARBINARY, authentication LONGVARBINARY ); create table oauth_code ( code VARCHAR(256), authentication LONGVARBINARY ); create table oauth_approvals ( userId VARCHAR(256), clientId VARCHAR(256), scope VARCHAR(256), status VARCHAR(10), expiresAt TIMESTAMP, lastModifiedAt TIMESTAMP ); -- customized oauth_client_details table create table ClientDetails ( appId VARCHAR(256) PRIMARY KEY, resourceIds VARCHAR(256), appSecret VARCHAR(256), scope VARCHAR(256), grantTypes VARCHAR(256), redirectUrl VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additionalInformation VARCHAR(4096), autoApproveScopes VARCHAR(256) );
4. demo案例1. 創(chuàng)建父工程pom.xml
文件如下
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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>pom</packaging> <modules> <module>oauth_resource</module> <module>oauth_server</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>springboot_security_oauth</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot_security_oauth</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <!--
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>
https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>
https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
2. 創(chuàng)建資源提供方模塊pom.xml
文件如下
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>springboot_security_oauth</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>oauth_resource</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> </dependencies> </project>
1. 配置application.yml
yml
server: port: 9002 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///test username: root password: root main: allow-bean-definition-overriding: true mybatis: type-aliases-package: com.example.domain configuration: map-underscore-to-camel-case: true logging: level: com.example: debug
2. 配置啟動類java
@SpringBootApplication @MapperScan("com.example.mapper") public class OAuthResourceApplication { public static void main(String[] args) { SpringApplication.run(OAuthResourceApplication.class, args); } }
3. 編寫一個資源路由java
@RestController @RequestMapping("/product") public class ProductController { @GetMapping public String findAll() { return "查詢產(chǎn)品列表成功!"; } }
4. 創(chuàng)建用戶pojo和角色pojo用戶pojojava
public class SysUser implements UserDetails { private Integer id; private String username; private String password; private Integer status; private List<SysRole> roles = new ArrayList<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public List<SysRole> getRoles() { return roles; } public void setRoles(List<SysRole> roles) { this.roles = roles; } @JsonIgnore @Override public Collection<? extends GrantedAuthority> getAuthorities() { return roles; } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @JsonIgnore @Override public boolean isAccountNonExpired() { return true; } @JsonIgnore @Override public boolean isAccountNonLocked() { return true; } @JsonIgnore @Override public boolean isCredentialsNonExpired() { return true; } @JsonIgnore @Override public boolean isEnabled() { return true; } }
角色pojojava
public class SysRole implements GrantedAuthority { private Integer id; private String roleName; private String roleDesc; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } //標(biāo)記此屬性不做json處理 @JsonIgnore @Override public String getAuthority() { return roleName; } }
5. 編寫資源管理配置類java
@Configuration @EnableResourceServer public class OauthResourceConfig extends ResourceServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private TokenStore tokenStore; /** * 指定token的持久化策略 * 其下有 RedisTokenStore保存到redis中, * JdbcTokenStore保存到數(shù)據(jù)庫中, * InMemoryTokenStore保存到內(nèi)存中等實現(xiàn)類, * 這里我們選擇保存在數(shù)據(jù)庫中 * * @return */ @Bean public TokenStore jdbcTokenStore() { return new JdbcTokenStore(dataSource); } public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.resourceId("product_api")//指定當(dāng)前資源的id,非常重要!必須寫! .tokenStore(tokenStore);//指定保存token的方式 } public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //指定不同請求方式訪問資源所需要的權(quán)限,一般查詢是read,其余是write。 .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')") .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')") .and() .headers().addHeaderWriter((request, response) -> { response.addHeader("Access-Control-Allow-Origin", "*");//允許跨域 if (request.getMethod().equals("OPTIONS")) {//如果是跨域的預(yù)檢請求,則原封不動向下傳達請求頭信息 response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method")); response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")); } }); } }
3. 創(chuàng)建授權(quán)模塊pom.xml
文件如下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>springboot_security_oauth</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>oauth_server</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> </dependencies> </project>
1. 配置application.yml
yml
server: port: 9001 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///test username: root password: root main: allow-bean-definition-overriding: true # 這個表示允許我們覆蓋OAuth2放在容器中的bean對象,一定要配置 mybatis: type-aliases-package: com.example.domain configuration: map-underscore-to-camel-case: true logging: level: com.example: debug
2. 配置啟動類java
@SpringBootApplication @MapperScan("com.example.mapper") public class OauthServerApplication { public static void main(String[] args) { SpringApplication.run(OauthServerApplication.class, args); } }
3. 創(chuàng)建用戶pojo和角色pojo用戶pojojava
public class SysUser implements UserDetails { private Integer id; private String username; private String password; private Integer status; private List<SysRole> roles = new ArrayList<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public List<SysRole> getRoles() { return roles; } public void setRoles(List<SysRole> roles) { this.roles = roles; } @JsonIgnore @Override public Collection<? extends GrantedAuthority> getAuthorities() { return roles; } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @JsonIgnore @Override public boolean isAccountNonExpired() { return true; } @JsonIgnore @Override public boolean isAccountNonLocked() { return true; } @JsonIgnore @Override public boolean isCredentialsNonExpired() { return true; } @JsonIgnore @Override public boolean isEnabled() { return true; } }
角色pojojava
public class SysRole implements GrantedAuthority { private Integer id; private String roleName; private String roleDesc; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } //標(biāo)記此屬性不做json處理 @JsonIgnore @Override public String getAuthority() { return roleName; } }
4. 編寫UserMapper
和RoleMapper
RoleMapper
java
public interface RoleMapper { @Select("select r.id,r.role_name roleName ,r.role_desc roleDesc " + "FROM sys_role r,sys_user_role ur " + "WHERE r.id=ur.rid AND ur.uid=#{uid}") public List<SysRole> findByUid(Integer uid); }
UserMapper
java
public interface UserMapper { @Select("select * from sys_user where username=#{username}") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "roles", column = "id", javaType = List.class, many = @Many(select = "com.example.mapper.RoleMapper.findByUid")) }) public SysUser findByUsername(String username); }
5. 編寫UserDetailService
的實現(xiàn)類UserService
java
public interface UserService extends UserDetailsService { }
UserServiceImpl
java
@Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return userMapper.findByUsername(username); } }
6. 編寫 SpringSecurity
配置類java
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserService userService; @Autowired private PasswordEncoder passwordEncoder; @Bean public PasswordEncoder myPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //所有資源必須授權(quán)后訪問 .anyRequest().authenticated() .and() .formLogin() .loginProcessingUrl("/login") .permitAll()//指定認證頁面可以匿名訪問 //關(guān)閉跨站請求防護 .and() .csrf().disable(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { //UserDetailsService類 auth.userDetailsService(userService) //加密策略 .passwordEncoder(passwordEncoder); } //AuthenticationManager對象在OAuth2認證服務(wù)中要使用,提取放入IOC容器中 @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
7. 編寫OAuth2
授權(quán)配置類java
@Configuration @EnableAuthorizationServer public class OauthServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private UserDetailsService userDetailsService; @Autowired private AuthenticationManager authenticationManager; @Autowired private PasswordEncoder passwordEncoder; //從數(shù)據(jù)庫中查詢出客戶端信息 @Bean public JdbcClientDetailsService clientDetailsService() { JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource); jdbcClientDetailsService.setPasswordEncoder(passwordEncoder); return jdbcClientDetailsService; } //token保存策略 @Bean public TokenStore tokenStore() { return new JdbcTokenStore(dataSource); } //授權(quán)信息保存策略 @Bean public ApprovalStore approvalStore() { return new JdbcApprovalStore(dataSource); } //授權(quán)碼模式專用對象 @Bean public AuthorizationCodeServices authorizationCodeServices() { return new JdbcAuthorizationCodeServices(dataSource); } //指定客戶端登錄信息來源 @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //從數(shù)據(jù)庫取數(shù)據(jù) clients.withClientDetails(clientDetailsService()); // 從內(nèi)存中取數(shù)據(jù) // clients.inMemory() // .withClient("baidu") // .secret(passwordEncoder.encode("12345")) // .resourceIds("product_api") // .authorizedGrantTypes( // "authorization_code", // "password", // "client_credentials", // "implicit", // "refresh_token" // )// 該client允許的授權(quán)類型 authorization_code,password,refresh_token,implicit,client_credentials // .scopes("read", "write")// 允許的授權(quán)范圍 // .autoApprove(false) // //加上驗證回調(diào)地址 // .redirectUris("
http://www.baidu.com"); } //檢測token的策略 @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.allowFormAuthenticationForClients() //允許form表單客戶端認證,允許客戶端使用client_id和client_secret獲取token .checkTokenAccess("isAuthenticated()") //通過驗證返回token信息 .tokenKeyAccess("permitAll()") // 獲取token請求不進行攔截 .passwordEncoder(passwordEncoder); } //OAuth2的主配置信息 @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .approvalStore(approvalStore()) .authenticationManager(authenticationManager) .authorizationCodeServices(authorizationCodeServices()) .tokenStore(tokenStore()) .userDetailsService(userDetailsService); } }
4. 測試4.1 授權(quán)碼模式測試在地址欄訪問地址
http://localhost:9001/oauth/authorize?response_type=code&client_id=baidu跳轉(zhuǎn)到
SpringSecurity
默認認證頁面,提示用戶登錄個人賬戶【這里是
sys_user
表中的數(shù)據(jù)】
登錄成功后詢問用戶是否給予操作資源的權(quán)限,具體給什么權(quán)限。
Approve
是授權(quán),
Deny
是拒絕。
這里我們選擇
read
和
write
都給予
Approve
。
點擊
Authorize
后跳轉(zhuǎn)到回調(diào)地址并獲取授權(quán)碼
使用授權(quán)碼到服務(wù)器申請通行令牌
token
測試攜帶通行令牌再次去訪問資源服務(wù)器資源路由
4.2 簡化模式測試在地址欄訪問地址
http://localhost:9001/oauth/authorize?response_type=token&client_id=baidu由于上面用戶已經(jīng)登錄過了,所以無需再次登錄,其實和上面是有登錄步驟的,這時,瀏覽器直接返回了token
使用剛才生成的
access_token
訪問資源服務(wù)器
4.3 密碼模式測試申請
token
使用剛才生成的
access_token
訪問資源服務(wù)器
4.4 客戶端模式測試申請token
使用剛才生成的
access_token
訪問資源服務(wù)器
感謝黑馬程序員提供的課程 分類: SpringBoot, 認證和授權(quán), SpringSecruity
收藏該文
if年少有為
關(guān)注 - 14
粉絲 - 47
+加關(guān)注
3
上一篇:SpringSecurity 整合SpringBoot結(jié)合jwt與rsa實現(xiàn)分布式認證授權(quán)?下一篇:springboot和springsecurity使用JWT令牌
posted @2020-01-13 19:30 if年少有為 閱讀(20446) 評論(13) 編輯 收藏 舉報
登錄后才能查看或發(fā)表評論,立即
登錄 或者
逛逛 博客園首頁
【推薦】華為開發(fā)者專區(qū),與開發(fā)者一起構(gòu)建萬物互聯(lián)的智能世界
【推薦】跨平臺組態(tài)/工控/仿真/CAD 50萬行C++源碼全開放免費下載!
【推薦】華為 HMS Core 線上 Codelabs 挑戰(zhàn)賽第4期,探索“智”感生活
編輯推薦:· 一文講透算法中的時間復(fù)雜度和空間復(fù)雜度計算方式
· .NET Core基礎(chǔ)篇:集成Swagger文檔與自定義Swagger UI
· 「譯」 .NET 6 中 gRPC 的新功能
· 一次緩存雪崩的災(zāi)難復(fù)盤
· 如何在 ASP.NET Core 中構(gòu)建輕量級服務(wù)
最新新聞:
· 農(nóng)村頂流為何沒在快手出現(xiàn)?(2021-12-14 10:29)
· 中國移動回A:12月22日申購 預(yù)計2021年營收超8448億(2021-12-14 10:14)
· 宗慶后傳宗不傳賢(2021-12-14 10:03)
· 打假穿越?。∥锢韺W(xué)告訴你:為什么我們不能穿越時空回到過去?(2021-12-14 09:55)
· 作惡的星巴克,“當(dāng)然是選擇不原諒他”(2021-12-14 09:42)
? 更多新聞...
站點概覽文章目錄
- 1. OAuth2.0介紹
- 2. OAuth2.0 中四種授權(quán)方式
- 1. 授權(quán)碼模式( authorization code)
- 流程
- 使用場景
- 2. 簡化模式(implicit)
- 流程
- 使用場景
- 3. 密碼模式(resource owner password credentials)
- 流程
- 使用場景
- 4. 客戶端模式(client credentials)
- 流程
- 使用場景
- 3. OAuth2.0 sql語句
- 4. demo案例
- 1. 創(chuàng)建父工程
- 2. 創(chuàng)建資源提供方模塊
- 1. 配置application.yml
- 2. 配置啟動類
- 3. 編寫一個資源路由
- 4. 創(chuàng)建用戶pojo和角色pojo
- 5. 編寫資源管理配置類
- 3. 創(chuàng)建授權(quán)模塊
- 1. 配置application.yml
- 2. 配置啟動類
- 3. 創(chuàng)建用戶pojo和角色pojo
- 4. 編寫UserMapper和RoleMapper
- 5. 編寫UserDetailService的實現(xiàn)類
- 6. 編寫 SpringSecurity配置類
- 7. 編寫OAuth2授權(quán)配置類
- 4. 測試
- 4.1 授權(quán)碼模式測試
- 4.2 簡化模式測試
- 4.3 密碼模式測試
- 4.4 客戶端模式測試
Copyright ? 2021 if年少有為
Powered by .NET 6 on Kubernetes