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.mzph.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…