一、本文简介

本文主要讲解Java编程中spring boot框架+spring security框架+spring security oauth2框架整合的例子,并且oauth2整合使用jwt方式存储

二、学习前提

首先是讲解oauth2的基本说明:

推荐查看:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

上面的地址可以基本了解下oauth2的原理

JWT的认知和基本使用:

推荐查看:

1.什么是JWT?

2.Java编程中java-jwt框架使用

三、代码编辑

开始代码:

认证服务:

几个核心的配置类:

AuthorizationServerConfiguration.java

package com.leftso.config.security;

import java.util.HashMap;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.core.userdetails.User;

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.TokenStore;

import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**

* 认证授权服务端

*

* @author leftso

*

*/

@Configuration

@EnableAuthorizationServer

public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

@Value("${resource.id:spring-boot-application}") // 默认值spring-boot-application

private String resourceId;

@Value("${access_token.validity_period:3600}") // 默认值3600

int accessTokenValiditySeconds = 3600;

@Autowired

private AuthenticationManager authenticationManager;

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

endpoints.authenticationManager(this.authenticationManager);

endpoints.accessTokenConverter(accessTokenConverter());

endpoints.tokenStore(tokenStore());

}

@Override

public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')");

oauthServer.checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");

}

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

clients.inMemory().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");

}

/**

* token converter

*

* @return

*/

@Bean

public JwtAccessTokenConverter accessTokenConverter() {

JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {

/***

* 重写增强token方法,用于自定义一些token返回的信息

*/

@Override

public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

String userName = authentication.getUserAuthentication().getName();

User user = (User) authentication.getUserAuthentication().getPrincipal();// 与登录时候放进去的UserDetail实现类一直查看link{SecurityConfiguration}

/** 自定义一些token属性 ***/

final Map additionalInformation = new HashMap<>();

additionalInformation.put("userName", userName);

additionalInformation.put("roles", user.getAuthorities());

((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);

OAuth2AccessToken enhancedToken = super.enhance(accessToken, authentication);

return enhancedToken;

}

};

accessTokenConverter.setSigningKey("123");// 测试用,资源服务使用相同的字符达到一个对称加密的效果,生产时候使用RSA非对称加密方式

return accessTokenConverter;

}

/**

* token store

*

* @param accessTokenConverter

* @return

*/

@Bean

public TokenStore tokenStore() {

TokenStore tokenStore = new JwtTokenStore(accessTokenConverter());

return tokenStore;

}

}

SecurityConfiguration.java

package com.leftso.config.security;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.HttpMethod;

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.core.authority.AuthorityUtils;

import org.springframework.security.core.userdetails.User;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.leftso.entity.Account;

import com.leftso.repository.AccountRepository;

@Configuration

@EnableGlobalMethodSecurity(prePostEnabled = true)

@EnableWebSecurity

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

// 查询用户使用

@Autowired

AccountRepository accountRepository;

@Autowired

public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {

// auth.inMemoryAuthentication()

// .withUser("user").password("password").roles("USER")

// .and()

// .withUser("app_client").password("nopass").roles("USER")

// .and()

// .withUser("admin").password("password").roles("ADMIN");

//配置用户来源于数据库

auth.userDetailsService(userDetailsService());

}

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest().authenticated().and()

.httpBasic().and().csrf().disable();

}

@Override

@Bean

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

}

@Bean

public UserDetailsService userDetailsService() {

return new UserDetailsService() {

@Override

public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {

// 通过用户名获取用户信息

Account account = accountRepository.findByName(name);

if (account != null) {

// 创建spring security安全用户

User user = new User(account.getName(), account.getPassword(),

AuthorityUtils.createAuthorityList(account.getRoles()));

return user;

} else {

throw new UsernameNotFoundException("用户[" + name + "]不存在");

}

}

};

}

}

受保护的资源服务:

核心配置:

SecurityConfiguration.java

package com.leftso.config;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.HttpMethod;

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration

@EnableGlobalMethodSecurity(prePostEnabled = true)

@EnableWebSecurity

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override

protected void configure(HttpSecurity http) throws Exception {

http

.authorizeRequests()

.antMatchers(HttpMethod.OPTIONS).permitAll()

.anyRequest().authenticated()

.and().httpBasic()

.and().csrf().disable();

}

}

ResourceServerConfiguration.java

package com.leftso.config;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.HttpMethod;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

import org.springframework.security.oauth2.provider.token.DefaultTokenServices;

import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;

import org.springframework.security.oauth2.provider.token.TokenStore;

import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import org.springframework.security.web.util.matcher.RequestMatcher;

/**

* 资源服务端

*

* @author leftso

*

*/

@Configuration

@EnableResourceServer

public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

@Value("${resource.id:spring-boot-application}")

private String resourceId;

@Override

public void configure(ResourceServerSecurityConfigurer resources) {

// @formatter:off

resources.resourceId(resourceId);

resources.tokenServices(defaultTokenServices());

// @formatter:on

}

@Override

public void configure(HttpSecurity http) throws Exception {

// @formatter:off

http.requestMatcher(new OAuthRequestedMatcher()).authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()

.anyRequest().authenticated();

// @formatter:on

}

private static class OAuthRequestedMatcher implements RequestMatcher {

public boolean matches(HttpServletRequest request) {

String auth = request.getHeader("Authorization");

// Determine if the client request contained an OAuth Authorization

boolean haveOauth2Token = (auth != null) && auth.startsWith("Bearer");

boolean haveAccessToken = request.getParameter("access_token") != null;

return haveOauth2Token || haveAccessToken;

}

}

// ===================================================以下代码与认证服务器一致=========================================

/**

* token存储,这里使用jwt方式存储

*

* @param accessTokenConverter

* @return

*/

@Bean

public TokenStore tokenStore() {

TokenStore tokenStore = new JwtTokenStore(accessTokenConverter());

return tokenStore;

}

/**

* Token转换器必须与认证服务一致

*

* @return

*/

@Bean

public JwtAccessTokenConverter accessTokenConverter() {

JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {

///***

// * 重写增强token方法,用于自定义一些token返回的信息

// */

//@Override

//public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

//String userName = authentication.getUserAuthentication().getName();

//User user = (User) authentication.getUserAuthentication().getPrincipal();// 与登录时候放进去的UserDetail实现类一直查看link{SecurityConfiguration}

///** 自定义一些token属性 ***/

//final Map additionalInformation = new HashMap<>();

//additionalInformation.put("userName", userName);

//additionalInformation.put("roles", user.getAuthorities());

//((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);

//OAuth2AccessToken enhancedToken = super.enhance(accessToken, authentication);

//return enhancedToken;

//}

};

accessTokenConverter.setSigningKey("123");// 测试用,授权服务使用相同的字符达到一个对称加密的效果,生产时候使用RSA非对称加密方式

return accessTokenConverter;

}

/**

* 创建一个默认的资源服务token

*

* @return

*/

@Bean

public ResourceServerTokenServices defaultTokenServices() {

final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();

defaultTokenServices.setTokenEnhancer(accessTokenConverter());

defaultTokenServices.setTokenStore(tokenStore());

return defaultTokenServices;

}

// ===================================================以上代码与认证服务器一致=========================================

}

项目源码下载:

https://github.com/leftso/demo-spring-boot-security-oauth2

四、测试上面的编码

测试过程

步骤一:打开浏览器,输入地址

http://localhost:8080/oauth/authorize?client_id=normal-app&response_type=code&scope=read&redirect_uri=/resources/user

会提示输入用户名密码,这时候输入用户名leftso,密码111aaa将会出现以下界面

点击Authorize将获取一个随机的code,如图:

打开工具postmain,输入以下地址获取授权token

localhost:8080/oauth/token?code=r8YBUL&grant_type=authorization_code&client_id=normal-app&redirect_uri=/resources/user

注意:url中的code就是刚才浏览器获取的code值

获取的token信息如下图:

这时候拿到token就可以访问受保护的资源信息了,如下

localhost:8081//resources/user

首先,直接访问资源,会报错401如图:

我们加上前面获取的access token再试:

localhost:8081//resources/user?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic3ByaW5nLWJvb3QtYXBwbGljYXRpb24iXSwidXNlcl9uYW1lIjoibGVmdHNvIiwic2NvcGUiOlsicmVhZCJdLCJyb2xlcyI6W3siYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn1dLCJleHAiOjE0OTEzNTkyMjksInVzZXJOYW1lIjoibGVmdHNvIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjgxNjI5NzQwLTRhZWQtNDM1Yy05MmM3LWZhOWIyODk5NmYzMiIsImNsaWVudF9pZCI6Im5vcm1hbC1hcHAifQ.YhDJkMSlyIN6uPfSFPbfRuufndvylRmuGkrdprUSJIM

这时候我们就能成功获取受保护的资源信息了:

到这里spring boot整合security oauth2 的基本使用已经讲解完毕.

五、扩展思维

留下一些扩展

1.认证服务的客户端信息是存放内存的,实际应用肯定是不会放内存的,考虑数据库,默认有个DataSource的方式,还有一个自己实现clientDetail接口方式

2.jwt这里测试用的最简单的对称加密,实际应用中使用的一般都是RSA非对称加密方式

jwt 例子 java_spring boot 入门之security oauth2 jwt完美整合例子-java编程相关推荐

  1. 学成在线-第16天-讲义- Spring Security Oauth2 JWT RSA加解密

    学成在线-第16天-讲义- Spring Security Oauth2 JWT 1 用户认证需求分析 1.1 用户认证与授权 ​ 截至目前,项目已经完成了在线学习功能,用户通过在线学习页面点播视频进 ...

  2. 【Spring Cloud Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...

  3. Spring Security Oauth2 JWT 实现用户认证授权功能

    Spring Security Oauth2 JWT 一 用户认证授权 1. 需求分析 1.1 用户认证与授权 什么是用户身份认证? 用户身份认证即用户去访问系统资源时系统要求验证用户的身份信息,身份 ...

  4. Spring boot 2.0 with Oauth2 + Jwt

    2019独角兽企业重金招聘Python工程师标准>>> Spring boot 2.0 with Oauth2 + Jwt 在这篇文章中: Netkiller Spring Clou ...

  5. 【Spring】Spring Security OAuth2 JWT 认证

    1.概述 Spring Security OAuth2 JWT 认证服务器配置 Spring Security OAuth2 JWT 资源服务器配置 Spring Security OAuth2 Re ...

  6. Spring Security OAuth2 JWT资源服务器配置

    1.POM相关依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId> ...

  7. 针对JWT简介与原理,代码实例,以及oauth2+JWT+RSA的集成配置

    JWT简介 JWT 是基于 RFC 7519 标准定义的一种可以安全传输的规范, 这个规范允许我们使用 JWT 在前后端之间传递安全可靠的信息. JWT 由于使用了数字签名,所以是可信任和安全的. 通 ...

  8. Spring Boot入门系列(十六)整合pagehelper,一秒实现分页功能!

    之前讲了Springboot整合Mybatis,然后介绍了如何自动生成pojo实体类.mapper类和对应的mapper.xml 文件,并实现最基本的增删改查功能.接下来要说一说Mybatis 的分页 ...

  9. 使用Spring Boot和Spring Security验证JWT

    对于我当前的项目,我将使用Spring Boot设置REST API (最有可能使用BoxFuse运行). 为了能够使用API​​端点,应用程序将检查传入的请求是否具有较早提供的有效JWT令牌 (由我 ...

最新文章

  1. iOS 关于手机权限的检查与获取
  2. Matlab并行编程方法
  3. 流水号结合自定义函数实现申请业务
  4. T-Mobile美国加速开展5G实验:28GHz频段成为新宠
  5. sdut 数据结构实验之排序三:bucket sort
  6. docker版iOS超级签应用分发平台源码分享[带免签封装]
  7. 汽车租赁php参考文献,国内外汽车租赁文献综述
  8. VC6.0建立新工程的步骤---解决win11使用不了VC6的方法以及自用版本VC6下载
  9. 爆款综艺也总火不过三季?谁来背锅?
  10. 毕业设计 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉
  11. 为什么《百家讲坛》上的中学教师收视率最高?
  12. 欧姆龙plc编程软件CX-Progammer v9.8升级教程
  13. FT2004(D2000)开发实战之W25X10CL固件烧写
  14. 纯CSS实现圆角阴影的折角效果
  15. 我的世界服务器修改高度放水,我的世界:水不够用?学会这4种方法,教你一桶水造无限水...
  16. 调用大智慧L2接口是什么原理?作用是什么?
  17. 40岁销售被裁员后抑郁了,学Python是他最后的希望
  18. onKeyUp方法简介
  19. 7.2 一次产品异常复位引发的质量提升经历
  20. verilog基本语法学习笔记

热门文章

  1. gem5中运行spec2006
  2. SpringCloud:Eureka Config项目搭建(Gradle项目)
  3. Mybatis基本使用步骤
  4. 深度模型(四):Transformer
  5. 怎么装修淘宝店铺才能提高转化率?分享6点小技巧给大家!
  6. 参考文献代码--学位论文做参考文献
  7. 如何自动获取ip地址(详解DHCP服务)
  8. ES6 语法 - Symbol
  9. python编程基础之二十七
  10. 在线伪原创-免费批量在线伪原创工具