SpringSecurity+Oauth2+Jwt的配置

前言

文章搭建工程基于Idea。
SpringSecurity+Oauth2+Jwt实现了什么功能?

SpringSecurity主要的工作就是拦截请求,只有满足基于springSecurity你定义的规则,才允许继续访问相应的资源或接口。可以说是一套权限管理的框架。能非常方便细致的帮助我们管理接口和资源的权限。
比如一个apicontroller里定义了多个接口,admin可以访问所有接口,角色1可以访问查询接口,角色2可以访问查询,添加接口,我们可以通过springsecurity的注解来区分权限。

这里要区分前后端权限的概念,比如说前端展示增加和查看按钮,但是没有删除按钮,但并不代表用户不能删除这条信息,只是用户没有操作界面去执行这个删除操作,假如用户知道删除接口地址,是同样可以删除这条消息的。所以后台接口这块也需要设置删除的权限验证。这样是最严谨的。

这里加上我自己的理解:springsecurity 建议用在后台管理对权限要求比较严的场景上,而针对app的接口服务,权限单一,还是尽量少用,主要是学习和使用成本太高。接手的人梳理代码逻辑就好久,这套框架是jsp时代的产物,还是尽量少用。不要被网络文章洗脑,感觉高大上,其实比较坑。

Oauth2负责请求权限token的颁发和验证规则,oauth主要是形成了一套规范的协议流程。用于实现第三方应用登录,假如没有这方面的需求,也不必费劲使用这套框架。

jwt就是具体的token形式 可以参考我的另外一篇文章。jwt的使用场景

什么情况下使用这套框架呢?

在开发类似微信的这种应用时,可以使用搞这套框架,因为许多其他的第三方应用都类似微信的授权登陆。

配置工程

初始化工程

New-->Project-->Spring Initializr-->下一步-->填写工程基本信息-->Web-->勾选Spring Web Starter--> Finish

导入pom

将pom.xml中的dependencies替换如下:

 <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <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-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.2</version>
        </dependency>
    </dependencies>

导入5个类,2个resource文件

具体文件如截图,

以上文件是最基础的配置,可以不用理解。以后直接复制到对应的工程里就可以。具体代码参见oauth2的git。

配置数据库

项目设置的默认数据库如下:

jdbc:mysql://localhost:3306/authtest

 在authtest数据库中,新建一个表,表名为oauth_client_details。插入语句如下:

DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
  `client_id` varchar(48) NOT NULL,
  `resource_ids` varchar(256) DEFAULT NULL,
  `client_secret` varchar(256) DEFAULT NULL,
  `scope` varchar(256) DEFAULT NULL,
  `authorized_grant_types` varchar(256) DEFAULT NULL,
  `web_server_redirect_uri` varchar(256) DEFAULT NULL,
  `authorities` varchar(256) DEFAULT NULL,
  `access_token_validity` int(11) DEFAULT NULL,
  `refresh_token_validity` int(11) DEFAULT NULL,
  `additional_information` varchar(4096) DEFAULT NULL,
  `autoapprove` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
INSERT INTO `oauth_client_details` VALUES ('app', null, 'app', 'app', 'password,refresh_token', 'http://localhost', null, null, null, null, null);
INSERT INTO `oauth_client_details` VALUES ('XcWebApp', null, '$2a$10$9bEpZ/hWRQxyr5hn5wHUj.jxFpIrnOmBcWlE/g/0Zp3uNxt9QTh/S', 'app', 'authorization_code,password,refresh_token,client_credentials', 'http://localhost', null, '43200', '43200', null, null);

 这个表的名称以及结构都是官方要求,也就是springsecurity源码中要访问的固定表名以及结构。

这个表的内容,可以理解为,这个授权服务器就是微信服务器,表里的数据,就是微信用户的用户名及密码等信息。

启动工程

现在就可以启动工程了,打开SpringBootApplication,运行main方法。然后访问http://localhost:8080/login。提示输入用户名及密码,在这里输入用户名XcWebApp和密码XcWebApp就可以登陆了。

到此我们基本搭建了一个springsecurity的服务器,怎么使用呢?需要继续往下看。

Oauth2的四种授权模式

  • 密码模式(resource owner password credentials)

  • 授权码模式(authorization code)

  • 简化模式(implicit)

  • 客户端模式(client credentials

一般使用的是前两种模式,后这两种使用在这里不做介绍,如果感兴趣可以去搜索下相关的使用配置

密码模式

授权码模式

 流程

先通过get请求获取授权码,然后通过post请求携带授权码获取token

获取授权码

http://localhost:8080/oauth/authorize?client_id=XcWebApp&response_type=code&scop=app&redirect_uri=http://localhost

上边get请求,附带几个参数参见数据库的几个字段,只有response_type是固定的code,其他的参数参考数据库表的内容。redirect_uri就是请求成功后重定向的地址。

通过访问这个地址,首先会提示你登陆,用户名密码都是XcWebApp(这块的用户名密码,你可以想象成你的应用接入微信平台的用户名密码)。输入完成后会进入授权页面(这个页面可以理解为微信弹出的授权框),点击授权按钮后,浏览器地址最后会附带一个code,这个code后边的值就是授权码

http://localhost/?code=A1YRMz

获取token

通过post请求获取token,这块使用postman提交post请求。

具体参数如下:

配置好参数后点击send,就会返回结果:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb21wYW55SWQiOiIxMjMyMjIiLCJ1c2VycGljIjoic2Rmc2RmIiwidXNlcl9uYW1lIjoiWGNXZWJBcHAiLCJzY29wZSI6WyJhcHAiXSwibmFtZSI6Im1ydCIsInV0eXBlIjoiYWRtaW4iLCJpZCI6IjIiLCJleHAiOjE1NjQzNDgxNzUsImp0aSI6IjkxNGZiOWExLTliMTgtNDljMC05YWE3LTNmZDdlNGVkMjNjNiIsImNsaWVudF9pZCI6IlhjV2ViQXBwIn0.bNhTFlGu3TldICkcMCK0q1rzzmQJL2M4pi6maP0eYyU_ZTCEcLpbSV3CkS_NjHLOUjnJKw5WP40lVTxZKFBFxV_7k_2Cr7R5BDseRDTPuVCDWBnd0XdGYpwQuXOPc9X6G3z1TQu9m6d3sTZpdVdq34XRrKWcdBkHIpaF_RjCgf13dH4f89aKKff03FA9OGUM_qeSx88XmnP6xns43_ZPN-ErhmhWIofczh1O2LyUaqYOCrRt17v0q0-k3cMqiZhtETHyZWn06H_gMUYgUVNJpG7U3JCE92I0v1TCQIBhYNPrIN9VjIAT6Lm0QO_yTCC5adG8Di1L1nLbmxo3sO0DnQ",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb21wYW55SWQiOiIxMjMyMjIiLCJ1c2VycGljIjoic2Rmc2RmIiwidXNlcl9uYW1lIjoiWGNXZWJBcHAiLCJzY29wZSI6WyJhcHAiXSwiYXRpIjoiOTE0ZmI5YTEtOWIxOC00OWMwLTlhYTctM2ZkN2U0ZWQyM2M2IiwibmFtZSI6Im1ydCIsInV0eXBlIjoiYWRtaW4iLCJpZCI6IjIiLCJleHAiOjE1NjQzNDgxNzUsImp0aSI6ImE5NjFlODAwLTVjMWQtNGZiMS05YmUwLTIyZDlkYWJmOTJlMCIsImNsaWVudF9pZCI6IlhjV2ViQXBwIn0.LHt4tvTrb319SpSXOmWTENdAlROPx2ooOsnK7DL98w8nzh3s3FuoPMR0ioCsmBPU4xyKamY1L5XnX8uc8hGkgf3rIzJLpW7qzy59jAJALXL_Owt8t-go3QUBsYJxK9JQrIPf3GE1tDc0EVXloBivxGhgj5GeXJdRSlITq7zMOkj3xCqxpAZeRA5Kl0Dqz9C5sRIbkcjEJTKtmkKymEJKPEbOJc8jRm61NUDCg6hH-hzDdqthrUvBud3sIfXF64b5nEYMlyWBSL_mtjiZsvwA3ejz2C1n3S4v_xzqbfHsWgWibuQ2pzIx6qrPUguGbx3dgv0UjfGpnKfHdrj6uwaHvQ",
    "expires_in": 43199,
    "scope": "app",
    "jti": "914fb9a1-9b18-49c0-9aa7-3fd7e4ed23c6"
}

 获得token后,以后访问其他网站资源,就可以通过springsecurity得认证了。否则会拦截你得请求。

 校验token

光顾着生成了,我们也是需要学会如何加密加密的token,springsecurity自带的校验地址:

http://localhost:8080/oauth/check_token?token=

校验后的结果如下:

{
	"companyId": "123222",
	"userpic": "sdfsdf",
	"user_name": "XcWebApp",
	"scope": ["app"],
	"name": "mrt",
	"utype": "admin",
	"active": true,
	"id": "2",
	"exp": 1564952248,
	"jti": "fbf07a90-890a-4899-b700-babf40816a8b",
	"client_id": "XcWebApp"
}

刷新token

就是将授权码中的grant_type字段的value设置为refresh_token即可,具体操作可百度搜索。这里不详细介绍。这个用处,假如app登陆token是3天有效期,如果用户每天都打开app,则token自动往后顺延3天,如果用户3天没有打开app,三天后token就失效。这块就用到刷新令牌。具体操作就是每次打开app都刷新下令牌即可。

其他文章参考

oauth流程原理详解

https://www.ruanyifeng.com/blog/2019/04/oauth_design.html

其实代码中很大一部分都是spring security的处理,所以明白spring security的流程和原理很重要

流程图参考

https://www.processon.com/view/5ec53844e401fd16f44be69a?fromnew=1

核心类详解 参考

https://blog.csdn.net/weixin_38982591/category_10048535.html

最简单的github demo,帮助理解

https://github.com/lansinuote/Spring-Oauth2-Toturials 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值