security和oauth2.0的整合
生活随笔
收集整理的這篇文章主要介紹了
security和oauth2.0的整合
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
security和oauth2.0的整合
之前已經(jīng)介紹過(guò)security的相關(guān)的介紹,現(xiàn)在所需要做的就是security和oauth2.0的整合,在原有的基礎(chǔ)上我們加上一些相關(guān)的代碼;代碼實(shí)現(xiàn)如下:
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><!--以下兩項(xiàng)需要如果不配置,解析themleaft 會(huì)有問(wèn)題--><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依賴(lài)--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.25</version></dependency><!--redis依賴(lài)--><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的依賴(lài)--><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>這里我們需要注意導(dǎo)入依賴(lài)的版本,版本過(guò)高可能會(huì)存在一些未知的問(wèn)題:
AuthorizationServerConfiguration核心類(lèi):
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;//認(rèn)證管理 很重要 如果security版本高可能會(huì)出坑哦@Resourceprivate AuthenticationManager authenticationManager;@Resourceprivate RedisAuthenticationCodeServices redisAuthenticationCodeServices;//定義令牌端點(diǎn)上的安全約束。@Overridepublic void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')");oauthServer.checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");}//將ClientDetailsServiceConfigurer(從您的回調(diào)AuthorizationServerConfigurer)可以用來(lái)在內(nèi)存或JDBC實(shí)現(xiàn)客戶(hù)的細(xì)節(jié)服務(wù)來(lái)定義的。客戶(hù)端的重要屬性是//clientId:(必填)客戶(hù)端ID。//secret:(可信客戶(hù)端需要)客戶(hù)機(jī)密碼(如果有)。//scope:客戶(hù)受限的范圍。如果范圍未定義或?yàn)榭?#xff08;默認(rèn)值),客戶(hù)端不受范圍限制。//authorizedGrantTypes:授予客戶(hù)端使用授權(quán)的類(lèi)型。默認(rèn)值為空。//authorities授予客戶(hù)的授權(quán)機(jī)構(gòu)(普通的Spring Security權(quán)威機(jī)構(gòu))。//客戶(hù)端的詳細(xì)信息可以通過(guò)直接訪(fǎng)問(wèn)底層商店(例如,在數(shù)據(jù)庫(kù)表中JdbcClientDetailsService)或通過(guò)ClientDetailsManager接口(這兩種實(shí)現(xiàn)ClientDetailsService也實(shí)現(xiàn))來(lái)更新運(yùn)行的應(yīng)用程序。//注意:JDBC服務(wù)的架構(gòu)未與庫(kù)一起打包(因?yàn)樵趯?shí)踐中可能需要使用太多變體)@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//默認(rèn)值InMemoryTokenStore對(duì)于單個(gè)服務(wù)器是完全正常的(即,在發(fā)生故障的情況下,低流量和熱備份備份服務(wù)器)。大多數(shù)項(xiàng)目可以從這里開(kāi)始,也可以在開(kāi)發(fā)模式下運(yùn)行,以便輕松啟動(dòng)沒(méi)有依賴(lài)關(guān)系的服務(wù)器。//這JdbcTokenStore是同一件事的JDBC版本,它將令牌數(shù)據(jù)存儲(chǔ)在關(guān)系數(shù)據(jù)庫(kù)中。如果您可以在服務(wù)器之間共享數(shù)據(jù)庫(kù),則可以使用JDBC版本,如果只有一個(gè),則擴(kuò)展同一服務(wù)器的實(shí)例,或者如果有多個(gè)組件,則授權(quán)和資源服務(wù)器。要使用JdbcTokenStore你需要“spring-jdbc”的類(lèi)路徑。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可以通過(guò)以下方式配置支持的授權(quán)類(lèi)型AuthorizationServerEndpointsConfigurer。默認(rèn)情況下,所有授權(quán)類(lèi)型均受支持,除了密碼(有關(guān)如何切換它的詳細(xì)信息,請(qǐng)參見(jiàn)下文)。以下屬性會(huì)影響授權(quán)類(lèi)型://authenticationManager:通過(guò)注入密碼授權(quán)被打開(kāi)AuthenticationManager。//userDetailsService:如果您注入U(xiǎn)serDetailsService或者全局配置(例如a GlobalAuthenticationManagerConfigurer),則刷新令牌授權(quán)將包含對(duì)用戶(hù)詳細(xì)信息的檢查,以確保該帳戶(hù)仍然活動(dòng)//authorizationCodeServices:定義AuthorizationCodeServices授權(quán)代碼授權(quán)的授權(quán)代碼服務(wù)(實(shí)例)。//implicitGrantService:在批準(zhǔn)期間管理狀態(tài)。//tokenGranter:(TokenGranter完全控制授予和忽略上述其他屬性)//在XML授予類(lèi)型中包含作為子元素authorization-server。/*** /oauth/authorize您可以從該請(qǐng)求中獲取所有數(shù)據(jù),* 然后根據(jù)需要進(jìn)行渲染,* 然后所有用戶(hù)需要執(zhí)行的操作都是回復(fù)有關(guān)批準(zhǔn)或拒絕授權(quán)的信息。* 請(qǐng)求參數(shù)直接傳遞給您UserApprovalHandler,* AuthorizationEndpoint所以您可以隨便解釋數(shù)據(jù)** @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(this.authenticationManager);endpoints.accessTokenConverter(accessTokenConverter());//jwtendpoints.tokenStore(tokenStore());//授權(quán)碼存儲(chǔ)endpoints.authorizationCodeServices(redisAuthenticationCodeServices);}@Beanpublic JwtAccessTokenConverter accessTokenConverter() {JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {/*** 重寫(xiě)增強(qiáng)token的方法* 自定義返回相應(yīng)的信息**/@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {String userName = authentication.getUserAuthentication().getName();// 與登錄時(shí)候放進(jìn)去的UserDetail實(shí)現(xiàn)類(lèi)一直查看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;}};// 測(cè)試用,資源服務(wù)使用相同的字符達(dá)到一個(gè)對(duì)稱(chēng)加密的效果,生產(chǎn)時(shí)候使用RSA非對(duì)稱(chēng)加密方式accessTokenConverter.setSigningKey("123");return accessTokenConverter;}@Beanpublic TokenStore tokenStore() {TokenStore tokenStore = new JwtTokenStore(accessTokenConverter());return tokenStore;}}RedisAuthenticationCodeServices:
我們把授權(quán)碼存在了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存儲(chǔ)授權(quán)碼 @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存儲(chǔ)@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;/**** 受保護(hù)的資源服務(wù)* @author leftso**/ @RestController @RequestMapping("/resources") public class ResourceController {/*** 需要用戶(hù)角色權(quán)限* @return*/@PreAuthorize("hasRole('ROLE_USER')")@RequestMapping(value="user", method=RequestMethod.GET)public String helloUser() {return "hello user";}/*** 需要管理角色權(quán)限* * @return*/@PreAuthorize("hasRole('ROLE_ADMIN')")@RequestMapping(value="admin", method=RequestMethod.GET)public String helloAdmin() {return "hello admin";}/*** 需要客戶(hù)端權(quán)限* * @return*/@PreAuthorize("hasRole('ROLE_CLIENT')")@RequestMapping(value="client", method=RequestMethod.GET)public String helloClient() {return "hello user authenticated by normal client";}/*** 需要受信任的客戶(hù)端權(quán)限* * @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轉(zhuǎn)載于:https://www.cnblogs.com/charlypage/p/9383415.html
總結(jié)
以上是生活随笔為你收集整理的security和oauth2.0的整合的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vscode - 添加背景图片
- 下一篇: Cisco ASA使用证书加密