security和oauth2.0的整合

security和oauth2.0的整合

之前已經介紹過security的相關的介紹,現在所需要做的就是security和oauth2.0的整合,在原有的基礎上我們加上一些相關的代碼;代碼實現如下:

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>urity.demo</groupId><artifactId>security-demo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><!--以下兩項需要如果不配置,解析themleaft 會有問題--><thymeleaf.version>3.0.2.RELEASE</thymeleaf.version><thymeleaf-layout-dialect.version>2.0.5</thymeleaf-layout-dialect.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Dalston.SR5</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>io.spring.platform</groupId><artifactId>platform-bom</artifactId><version>Brussels-SR9</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--mybatis與mysql--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.2.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--druid依賴--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.25</version></dependency><!--redis依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--jasypt加解密--><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>1.14</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><!--oauth2.0--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-jwt</artifactId></dependency><!--feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-feign</artifactId></dependency><!--session集群管理--><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><!--zipkin--><!-- <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-sleuth-zipkin</artifactId></dependency>--><!--eureka--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--添加static和templates的依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--config--><!--<dependency>--><!--<groupId>org.springframework.cloud</groupId>--><!--<artifactId>spring-cloud-starter-config</artifactId>--><!--</dependency>--><!--<dependency>--><!--<groupId>org.springframework.cloud</groupId>--><!--<artifactId>spring-cloud-starter-bus-amqp</artifactId>--><!--</dependency>--></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

這里我們需要注意導入依賴的版本,版本過高可能會存在一些未知的問題:

AuthorizationServerConfiguration核心類:

package urity.demo.oauth2;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
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.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import urity.demo.service.RedisAuthenticationCodeServices;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {@Value("${resource.id:spring-boot-application}")private String resourceId;@Value("${access_token.validity_period:36000}")private int accessTokenValiditySeconds = 36000;//認證管理 很重要 如果security版本高可能會出坑哦@Resourceprivate AuthenticationManager authenticationManager;@Resourceprivate RedisAuthenticationCodeServices redisAuthenticationCodeServices;//定義令牌端點上的安全約束。@Overridepublic void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')");oauthServer.checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");}//將ClientDetailsServiceConfigurer(從您的回調AuthorizationServerConfigurer)可以用來在內存或JDBC實現客戶的細節服務來定義的。客戶端的重要屬性是//clientId:(必填)客戶端ID。//secret:(可信客戶端需要)客戶機密碼(如果有)。//scope:客戶受限的范圍。如果范圍未定義或為空(默認值),客戶端不受范圍限制。//authorizedGrantTypes:授予客戶端使用授權的類型。默認值為空。//authorities授予客戶的授權機構(普通的Spring Security權威機構)。//客戶端的詳細信息可以通過直接訪問底層商店(例如,在數據庫表中JdbcClientDetailsService)或通過ClientDetailsManager接口(這兩種實現ClientDetailsService也實現)來更新運行的應用程序。//注意:JDBC服務的架構未與庫一起打包(因為在實踐中可能需要使用太多變體)@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//默認值InMemoryTokenStore對于單個服務器是完全正常的(即,在發生故障的情況下,低流量和熱備份備份服務器)。大多數項目可以從這里開始,也可以在開發模式下運行,以便輕松啟動沒有依賴關系的服務器。//這JdbcTokenStore是同一件事的JDBC版本,它將令牌數據存儲在關系數據庫中。如果您可以在服務器之間共享數據庫,則可以使用JDBC版本,如果只有一個,則擴展同一服務器的實例,或者如果有多個組件,則授權和資源服務器。要使用JdbcTokenStore你需要“spring-jdbc”的類路徑。clients.inMemory()//client Id.withClient("normal-app").authorizedGrantTypes("authorization_code", "implicit").authorities("ROLE_CLIENT").scopes("read","write").resourceIds(resourceId).accessTokenValiditySeconds(accessTokenValiditySeconds).and().withClient("trusted-app").authorizedGrantTypes("client_credentials", "password").authorities("ROLE_TRUSTED_CLIENT").scopes("read", "write").resourceIds(resourceId).accessTokenValiditySeconds(accessTokenValiditySeconds).secret("secret");}//AuthorizationEndpoint可以通過以下方式配置支持的授權類型AuthorizationServerEndpointsConfigurer。默認情況下,所有授權類型均受支持,除了密碼(有關如何切換它的詳細信息,請參見下文)。以下屬性會影響授權類型://authenticationManager:通過注入密碼授權被打開AuthenticationManager。//userDetailsService:如果您注入UserDetailsService或者全局配置(例如a GlobalAuthenticationManagerConfigurer),則刷新令牌授權將包含對用戶詳細信息的檢查,以確保該帳戶仍然活動//authorizationCodeServices:定義AuthorizationCodeServices授權代碼授權的授權代碼服務(實例)。//implicitGrantService:在批準期間管理狀態。//tokenGranter:(TokenGranter完全控制授予和忽略上述其他屬性)//在XML授予類型中包含作為子元素authorization-server。/*** /oauth/authorize您可以從該請求中獲取所有數據,* 然后根據需要進行渲染,* 然后所有用戶需要執行的操作都是回復有關批準或拒絕授權的信息。* 請求參數直接傳遞給您UserApprovalHandler,* AuthorizationEndpoint所以您可以隨便解釋數據** @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(this.authenticationManager);endpoints.accessTokenConverter(accessTokenConverter());//jwtendpoints.tokenStore(tokenStore());//授權碼存儲endpoints.authorizationCodeServices(redisAuthenticationCodeServices);}@Beanpublic JwtAccessTokenConverter accessTokenConverter() {JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {/*** 重寫增強token的方法* 自定義返回相應的信息**/@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {String userName = authentication.getUserAuthentication().getName();// 與登錄時候放進去的UserDetail實現類一直查看link{SecurityConfiguration}User user = (User) authentication.getUserAuthentication().getPrincipal();/** 自定義一些token屬性 ***/final Map<String, Object> additionalInformation = new HashMap<>();additionalInformation.put("userName", userName);additionalInformation.put("roles", user.getAuthorities());((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);OAuth2AccessToken enhancedToken = super.enhance(accessToken, authentication);return enhancedToken;}};// 測試用,資源服務使用相同的字符達到一個對稱加密的效果,生產時候使用RSA非對稱加密方式accessTokenConverter.setSigningKey("123");return accessTokenConverter;}@Beanpublic TokenStore tokenStore() {TokenStore tokenStore = new JwtTokenStore(accessTokenConverter());return tokenStore;}}

RedisAuthenticationCodeServices:

我們把授權碼存在了redis中:

package urity.demo.service;import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.security.oauth2.common.util.SerializationUtils;//自定義為使用redis存儲授權碼
@Service
@Slf4j
public class RedisAuthenticationCodeServices extends RandomValueAuthorizationCodeServices {private static final String AUTH_CODE_KEY = "my_code";private RedisConnectionFactory connectionFactory;public RedisAuthenticationCodeServices(RedisConnectionFactory connectionFactory) {Assert.notNull(connectionFactory, "RedisConnectionFactory required");this.connectionFactory = connectionFactory;}private RedisConnection getConnection() {return connectionFactory.getConnection();}//redis存儲@Overrideprotected void store(String code, OAuth2Authentication authentication) {RedisConnection conn = getConnection();try {conn.hSet(AUTH_CODE_KEY.getBytes("utf-8"), code.getBytes("utf-8"),SerializationUtils.serialize(authentication));} catch (Exception e) {conn.close();}}@Overrideprotected OAuth2Authentication remove(String code) {RedisConnection conn = getConnection();try {OAuth2Authentication authentication = null;try {authentication = SerializationUtils.deserialize(conn.hGet(AUTH_CODE_KEY.getBytes("utf-8"),code.getBytes("utf-8")));} catch (Exception e) {e.printStackTrace();}if (authentication != null) {conn.hDel(AUTH_CODE_KEY.getBytes("utf-8"),code.getBytes("utf-8"));}return authentication;} catch (Exception e) {e.printStackTrace();} finally {conn.close();}return null;}
}

ResourceController:

package urity.demo.controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;/**** 受保護的資源服務* @author leftso**/
@RestController
@RequestMapping("/resources")
public class ResourceController {/*** 需要用戶角色權限* @return*/@PreAuthorize("hasRole('ROLE_USER')")@RequestMapping(value="user", method=RequestMethod.GET)public String helloUser() {return "hello user";}/*** 需要管理角色權限* * @return*/@PreAuthorize("hasRole('ROLE_ADMIN')")@RequestMapping(value="admin", method=RequestMethod.GET)public String helloAdmin() {return "hello admin";}/*** 需要客戶端權限* * @return*/@PreAuthorize("hasRole('ROLE_CLIENT')")@RequestMapping(value="client", method=RequestMethod.GET)public String helloClient() {return "hello user authenticated by normal client";}/*** 需要受信任的客戶端權限* * @return*/@PreAuthorize("hasRole('ROLE_TRUSTED_CLIENT')")@RequestMapping(value="trusted_client", method=RequestMethod.GET)public String helloTrustedClient() {return "hello user authenticated by trusted client";}@RequestMapping(value="principal", method=RequestMethod.GET)public Object getPrincipal() {Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();return principal;}@RequestMapping(value="roles", method=RequestMethod.GET)public Object getRoles() {return SecurityContextHolder.getContext().getAuthentication().getAuthorities();}}

application.xml:

server:port: 8787
spring:redis:host: 127.0.0.1port: 6379
#    password: redisdatabase: 0datasource:url: jdbc:mysql://localhost:3306/testusername: ***password: ***driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceinitialSize: 5minIdle: 5maxActive: 30maxWait: 10000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMills: 300000session:store-type: none
other:security:oauth2:signKey: oauth

轉載于:https://www.cnblogs.com/charlypage/p/9383415.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249854.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249854.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249854.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于Vue.use()詳解

問題 相信很多人在用Vue使用別人的組件時&#xff0c;會用到 Vue.use() 。例如&#xff1a;Vue.use(VueRouter)、Vue.use(MintUI)。但是用 axios時&#xff0c;就不需要用 Vue.use(axios)&#xff0c;就能直接使用。那這是為什么吶&#xff1f; 答案 因為 axios 沒有 install。…

百度TTS的來由

#### https://home-assistant.io/components/tts.baidu/#### https://github.com/charleyzhu/HomeAssistant_Components#### 當前使用自定義組件 https://bbs.hassbian.com/thread-1152-1-1.html#### 2018-3-15添加百度云語音識別 - platform: baidu language: zh app_i…

eslint 禁用命令

/* eslint-disable */ ESLint 在校驗的時候就會跳過后面的代碼還可以在注釋后加入詳細規則&#xff0c;這樣就能避開指定的校驗規則了/* eslint-disable no-new */常用&#xff1a; rules: {"comma-dangle": ["error", "never"], //是否允許對象…

分布式工具的一次小升級?

前言 之前在做 秒殺架構實踐 時有提到對 distributed-redis-tool 的一次小升級&#xff0c;但是沒有細說。 其實主要原因是&#xff1a; 秒殺時我做壓測&#xff1a;由于集成了這個限流組件&#xff0c;并發又比較大&#xff0c;所以導致連接、斷開 Redis 非常頻繁。 最終導致獲…

淺談vue $mount()

Vue 的$mount()為手動掛載&#xff0c;在項目中可用于延時掛載&#xff08;例如在掛載之前要進行一些其他操作、判斷等&#xff09;&#xff0c;之后要手動掛載上。new Vue時&#xff0c;el和$mount并沒有本質上的不同。 具體見代碼&#xff1a; 順便附上vue渲染機制流程圖&a…

小三角

{border-color: transparent;border-right-color: #e5e5e5;border-width: 7px;margin-top: -7px;right: 100%;top: 20px;border: solid transparent;content: " ";height: 0;width: 0;position: absolute;pointer-events: none; }轉載于:https://www.cnblogs.com/smz…

Laravel日志查看器 -- log-viewer擴展

1.修改laravel配置文件. config\app.php log>daily 2.在項目目錄中composer命令安裝擴展&#xff1a;composer require arcanedev/log-viewer 3.安裝成功后&#xff0c;需要在config\app.php 的providers陣列中注冊服務 Arcanedev\LogViewer\LogViewerServiceProvider::clas…

論一個程序員的自我修養-從一張圖片說起

故事起源 本來今天想寫.NET Core實戰之CMS系統第十五篇文章的。哈&#xff0c;奈何今天在新生命人脈群里面看到石頭哥分享的一張圖片&#xff0c;然后大家就議論了起來&#xff0c;不過我看的很懵逼&#xff0c;這圖什么意思啊&#xff1f;當一個朋友講述了這個圖片背后的故事的…

vue實例屬性之el,template,render

一、el&#xff0c;template&#xff0c;render屬性優先性 當Vue選項對象中有render渲染函數時&#xff0c;Vue構造函數將直接使用渲染函數渲染DOM樹&#xff0c;當選項對象中沒有render渲染函數時&#xff0c;Vue構造函數首先通過將template模板編譯生成渲染函數&#xff0c;然…

mysql8的坑

plugin caching_sha2_password could not be loaded 我在mac上用Sequel Pro連數據庫的時候&#xff0c;會報出以上錯誤&#xff0c;這是應為8.0.11把身份認證插件改成了 caching_sha2_password &#xff0c;而客戶端沒法使用此插件。 這是我們只要用命令行進去mysql&#xff0c…

c/c++ 繼承與多態 文本查詢的小例子(非智能指針版本)

問題&#xff1a;在上一篇繼承與多態 文本查詢的小例子&#xff08;智能指針版本&#xff09;在Query類里使用的是智能指針&#xff0c;只把智能指針換成普通的指針&#xff0c;并不添加拷貝構造方法&#xff0c;會發生什么呢&#xff1f; 執行時&#xff0c;代碼崩掉。 分析下…

day19_生成器

20180730 初次上傳 20180731 更新&#xff0c;4、列表生成式&#xff0c;以及部分注釋 #!/usr/bin/env python # -*- coding:utf-8 -*-# ********************day19_生成器 ******************* # ********************day19_生成器 ******************* # *******************…

HTML渲染過程詳解

由于本人對http協議以及dns對url的解析問題并不了解&#xff0c;所以這里之探討url請求加載到瀏覽器端時&#xff0c;瀏覽器對html的解析到呈現過程&#xff0c;后來經過幾位道友分享&#xff0c;整理了一下url解析的過程&#xff0c;如下&#xff1a; 用戶輸入url地址&#x…

grid布局

CSS Grid 布局CSS 中最強大的布局系統。與 flexbox 的一維布局系統不同&#xff0c;CSS Grid 布局是一個二維布局系統&#xff0c;也就意味著它可以同時處理列和行。通過將 CSS 規則應用于 父元素 (成為 Grid Container 網格容器)和其 子元素&#xff08;成為 Grid Items 網格項…

vue之router-view組件的使用

開發的時候有時候會遇到一種情況&#xff0c;比如 &#xff1a;點擊這個鏈接跳轉到其他組件的情況&#xff0c;通常會跳轉到新的頁面&#xff0c;蛋是&#xff0c;我們不想跳轉到新頁面&#xff0c;只在當前頁面切換著顯示&#xff0c;那么就要涉及到路由的嵌套了&#xff0c;也…

go 學習Printf

package main import "fmt" import "os" type point struct {x, y int } func main() { //Go 為常規 Go 值的格式化設計提供了多種打印方式。例如&#xff0c;這里打印了 point 結構體的一個實例。p : point{1, 2}fmt.Printf("%v\n", p) // {1 2…

博客園使用latex編輯公式

如何開啟數學公式編輯功能 開啟方法見下鏈接https://www.cnblogs.com/cmt/p/3279312.html 功能 支持數學公式塊支持文中數學公式DEMO $$ f(n) \begin{cases}\frac{n}{2}, & \text{if $n$ is even} \\3n1, & \text{if $n$ is odd}\end{cases} $$ 以上的代碼產生如下的公…

console.dir有很多瀏覽器,系統的兼容性問題,不要隨便用!

console.dir有很多瀏覽器&#xff0c;系統的兼容性問題&#xff0c;不要隨便用&#xff01; 要使用console.log();轉載于:https://www.cnblogs.com/bluestear/p/9400356.html

go 區分指針

先看一段代碼 先放一段代碼&#xff0c;人工運行一下&#xff0c;看看自己能做對幾題&#xff1f; package mainimport "fmt"func main() {var a int 1 var b *int &a var c **int &b var x int *b fmt.Println("a ",a) fmt.Println("&a…

ajax和axios、fetch的區別

1.jQuery ajax $.ajax({type: POST,url: url,data: data,dataType: dataType,success: function () {},error: function () {} });傳統 Ajax 指的是 XMLHttpRequest&#xff08;XHR&#xff09;&#xff0c; 最早出現的發送后端請求技術&#xff0c;隸屬于原始js中&#xff0c…