jwt 例子 java_spring boot 入门之security oauth2 jwt完美整合例子-java编程
一、本文简介
本文主要讲解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编程相关推荐
- 学成在线-第16天-讲义- Spring Security Oauth2 JWT RSA加解密
学成在线-第16天-讲义- Spring Security Oauth2 JWT 1 用户认证需求分析 1.1 用户认证与授权 截至目前,项目已经完成了在线学习功能,用户通过在线学习页面点播视频进 ...
- 【Spring Cloud Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权
一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...
- Spring Security Oauth2 JWT 实现用户认证授权功能
Spring Security Oauth2 JWT 一 用户认证授权 1. 需求分析 1.1 用户认证与授权 什么是用户身份认证? 用户身份认证即用户去访问系统资源时系统要求验证用户的身份信息,身份 ...
- Spring boot 2.0 with Oauth2 + Jwt
2019独角兽企业重金招聘Python工程师标准>>> Spring boot 2.0 with Oauth2 + Jwt 在这篇文章中: Netkiller Spring Clou ...
- 【Spring】Spring Security OAuth2 JWT 认证
1.概述 Spring Security OAuth2 JWT 认证服务器配置 Spring Security OAuth2 JWT 资源服务器配置 Spring Security OAuth2 Re ...
- Spring Security OAuth2 JWT资源服务器配置
1.POM相关依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId> ...
- 针对JWT简介与原理,代码实例,以及oauth2+JWT+RSA的集成配置
JWT简介 JWT 是基于 RFC 7519 标准定义的一种可以安全传输的规范, 这个规范允许我们使用 JWT 在前后端之间传递安全可靠的信息. JWT 由于使用了数字签名,所以是可信任和安全的. 通 ...
- Spring Boot入门系列(十六)整合pagehelper,一秒实现分页功能!
之前讲了Springboot整合Mybatis,然后介绍了如何自动生成pojo实体类.mapper类和对应的mapper.xml 文件,并实现最基本的增删改查功能.接下来要说一说Mybatis 的分页 ...
- 使用Spring Boot和Spring Security验证JWT
对于我当前的项目,我将使用Spring Boot设置REST API (最有可能使用BoxFuse运行). 为了能够使用API端点,应用程序将检查传入的请求是否具有较早提供的有效JWT令牌 (由我 ...
最新文章
- iOS 关于手机权限的检查与获取
- Matlab并行编程方法
- 流水号结合自定义函数实现申请业务
- T-Mobile美国加速开展5G实验:28GHz频段成为新宠
- sdut 数据结构实验之排序三:bucket sort
- docker版iOS超级签应用分发平台源码分享[带免签封装]
- 汽车租赁php参考文献,国内外汽车租赁文献综述
- VC6.0建立新工程的步骤---解决win11使用不了VC6的方法以及自用版本VC6下载
- 爆款综艺也总火不过三季?谁来背锅?
- 毕业设计 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉
- 为什么《百家讲坛》上的中学教师收视率最高?
- 欧姆龙plc编程软件CX-Progammer v9.8升级教程
- FT2004(D2000)开发实战之W25X10CL固件烧写
- 纯CSS实现圆角阴影的折角效果
- 我的世界服务器修改高度放水,我的世界:水不够用?学会这4种方法,教你一桶水造无限水...
- 调用大智慧L2接口是什么原理?作用是什么?
- 40岁销售被裁员后抑郁了,学Python是他最后的希望
- onKeyUp方法简介
- 7.2 一次产品异常复位引发的质量提升经历
- verilog基本语法学习笔记