百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

十年架构师爆肝分享:基于SpringSecurity实现的基本认证及OAuth2

toyiye 2024-09-16 06:07 3 浏览 0 评论

实现安全机制

本节将介绍基于Spring Security实现的基本认证及OAuth2。

实现基本认证

如果Spring Security位于类路径上,则所有HTTP端点上默认使用基本认证,这样就能使Web应用程序得到一定的安全保障。最为快捷的方式是在依赖中添加Spring Boot Security Starter。

//依赖关系
dependencies {
//该依赖用于编译阶段
compile('org.springf ramework . boot : spring-boot-starter-security')

如果要向Web应用程序添加方法级别的安全保障,还可以在Spring Boot应用里面添加@Ena-bleGlobalMethodSecurity注解来实现,如下面的例子所示。

@EnableGlobalMe thodsecurity
@SpringBootApplication
public class Application {
public static void main (String[] args) {
SpringApplication. run (Application.class, args) ;

需要注意的是,@EnableGlobalMethodSecurity 可以配置多个参数:

prePostEnabled:决定Spring Security的前注解是否可用@PreAuthorize、@PostAuthorize 等;

secureEnabled:决定Spring Security的保障注解@Secured是否可用;

jsr250Enabled :决定JSR-250注解@RolesAllowed等是否可用。

配置方式分别如下。

@EnableGlobalMethodSecurity (securedEnabled = true)
public class MethodSecuri tyConfig {
// ...
@EnableGlobalMethodSecurity (jsr250Enabled = true)
public class MethodSecurityConfig {
//...
@EnableGlobalMe thodsecurity (prePostEnabled = true)
public class MethodSecurityConfig {
/...
}

在同一个应用程序中,可以启用多个类型的注解,但是对于行为类的接口或类只应该设置一个注解。如果将2个注解同时应用于某- -特定方法, 则只有其中-一个被应用。

1. @Secured

此注解是用来定义业务方法的安全配置属性的列表。您可以在需要安全角色1权限等的方法上指定@Secured,并且只有那些角色1权限的用户才可以调用该方法。如果有人不具备要求的角色1权限但试图调用此方法,将会抛出AccessDenied 异常。

@Secured源于Spring 之前的版本,它有一个局限就是不支持Spring EL表达式。可以看看下面的例子。

如果你想指定AND (和)这个条件,即deleteUser方法只能被同时拥有ADMIN & DBA,但是仅仅通过使用@Secured注解是无法实现的。

但是你可以使用Spring新的注解@PreAuthorize/@PostAuthorize (支持Spring EL),使实现上面的功能成为可能,而且无限制。

@PreAuthori ze/@PostAuthorize

Spring的@PreAuthorize/@PostAuthorize 注解更适合方法级的安全,也支持Spring EL表达式

语言,提供了基于表达式的访问控制。

●@PreAuthorize 注解:适合进入方法前的权限验证,@PreAuthorize 可以将登录用户的角色1权

限参数传到方法中。

●@PostAuthorize注解:使用并不多,在方法执行后再进行权限验证。

以下是-一个使用了@PreAuthorize 注解的例子。

@PreAuthorize ("hasAuthority('ROLE ADMIN')") // 指定角色权限才能操作方法
@GetMapping(value = "delete/ {id}")
public ModelAndView delete (@PathVariable ("id") Long id, Model model) {
userService. removeUser (id) ;
model . addAttribute ("userList", userService. listUsers()) ;
model. addAttribute("title", "删除用户");
return new ModelAndView ("users/list", "userModel", model) ;}

2.登录账号和密码

默认的AuthenticationManager具有单个用户账号,其中用户名称是“user",密码是一个随机码,在应用程序启动时以INFO级别打印,如下所示。

Using default security password: 78fa195d-3f4c-48b1-ad50-e24c31d5cf36

当然,你也可以在配置文件中来自定义用户名和密码。

security . user . name=guest
security. user . password=guest123

实现0Auth2认证

如果您的类路径中有spring-security-oauth2, 则可以利用某些自动配置来轻松设置授权或资源服务器,即可实现OAuth2认证。

1.什么是OAuth 2.0

OAuth 2.0的规范可以参考RFC 6749 ( ht:t/ols.ietf.org/htm/fc6749 )。

OAuth是一个开放标准,允许用户让第三方应用访问该用户在某- -网站上存储的私密的资源(如照片、视频、联系人列表等),而无须将用户名和密码提供给第三方应用。目前,OAuth的最新版本为2.0。

OAuth允许用户提供-一个令牌 ,而不是用户名和密码来访问他们存放在特定服务提供者的数据。

每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如,仅仅是某一.相册中的视频) 。这样, OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享它们的访问许可或数据的所有内容。

2. OAuth 2.0的核心概念

0Auth2.0主要有以下4类角色。.

resource owner:

资源所有者,指终端的“用户”( user )

resource server:资源服务器,即服务提供商存放受保护资源。访问这些资源,需要获得访问令牌( Access Token)。它与认证服务器可以是同一台服务器,也可以是不同的服务器。如果我们访问新浪博客网站,那么如果使用新浪博客的账号来登录新浪博客网站,那么新浪博客的资源和新浪博客的认证都是同- -家,可以认为是同一个服务器。如果我们使用新浪博客账号去登录知乎,那么显然知乎的资源和新浪的认证不是-一个服务器。

client:客户端,代表向受保护资源进行资源请求的第三方应用程序。

authorization server : .

授权服务器,在验证资源所有者并获得授权成功后,将发放访问令牌给客户端。

3. OAuth 2.0的认证流程

OAuth 2.0的认证流程如下。

①用户打开客户端以后,客户端请求资源所有者(用户)的授权。

②用户同意给予客户端授权。

③客户端使用上一步获得的授权,向认证服务器申请访问令牌。

④认证服务器对客户端进行认证以后,确认无误,同意发放访问令牌。

⑤客户端使用访问令牌,向资源服务器申请获取资源。

⑥资源服务器确认令牌无误,同意向客户端开放资源。

其中,用户授权有以下4种模式:

授权码模式( authorization code) ;

简化模式( implicit) ;

密码模式( resource owner password credentials) ;

客户端模式( client credentials)。

4.配置

项目的核心配置如下。

github. cl ient. clientId=ad2abbc19b6c5f0ed117
gi thub. client. clientSecret=26db88a4dfc34cebaf196e68761c1294ac4ce265
gi thub.c1 ient. accessTokenUri=https://gi thub. com/1ogin/ oauth/access_
token
github. client .userAuthorizationUri=https:/ /github. com/ login/ oauth/
authorize
gi thub. client.clientAuthenticationScheme-form 
gi thub. client. tokenName=oauth_ token
github. client.authenticationScheme=query
gi thub. resource .userInfoUri=https:/ /api .github. com/user

包括了作为一个client所需要的大部分参数。其中clientId、 clientSecret 是在GitHub注册一个应用时生成的。如果读者不想注册应用,则可以直接使用上面的配置。如果要注册,则文章最后有注册流程。

5.项目安全的配置

安全配置中需要加上@EnableWebSecurity、@EnableOAuth2Client 注解,来启用Web安全认证机制,并表明这是一个OAuth 2.0客户端。@EnableGlobalMethodScurity 注明,项目采用了基于方法的安全设置。

@EnableWebSecurity
@EnableOAuth2Client
//启用0Auth2.0客户端
@EnableGlobalMethodSecurity (prePostEnabledtrue)
启用方法安全设置
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//...
}

使用Spring Security,我们需要继承org. springframework. security config. antationweb.configura-tion. WebSecurityConfigurerAdapter并重写以下configure 方法。

@Override
protected void configure (HttpSecurity http) throws Exception {
http. addFilterBefore (ssoFilter(), BasicAuthenticationFilter.class)
. antMatcher ("/**")
. authori zeRequests ()
. antMatchers("/", "/index", "/403", "/css/**", "/js/**", "/
fonts/**") .permitAll() //不设限制,都允许访问
. anyRequest ()
. authenticated()
.and() .logout () . logoutSuccessUrl ("/") . permitAll ()
.and() .csrf () . csrfTokenRepository (CookieCsrfTokenRepository.
wi thHttpOnlyFalse() )

上面的配置是设置了一些过滤策略,除了静态资源及不需要授权的页面,我们允许访问其他的资源,都需要授权访问。

其中,我们也设置了一个过滤器ssoFiter,用于在BasicAuthenticationFilter之前进行拦截。如果拦截到的是/login,就是访问认证服务器。
private Filter ssoFilter () {
OAuth2ClientAuthenticationProcessingFilter githubFilter = new OAu-
th2ClientAuthenticationProcessingFilter ("/login") ;
OAuth2RestTemplate githubTemplate = new OAuth2Res tTemplate (github(),
oauth2Cl ientContext) ;
gi thubFilter. setRestTemplate (gi thubTemplate) ;
UserInfoTokenServices tokenServices = new UserInfoTokenServices
(githubResource () .getUserInfoUri (),github() .getClientId());
tokenServices. setRestTemplate (githubTemplate) ;
githubFilter. setTokenServices (tokenServices) ;
return githubFilter;
@Bean
public FilterRegistrationBean oauth2C1 ientFilterRegistration (
OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean() ;
registration.setFilter (filter) ;
registration. setOrder(-100) ;
return registration;
@Bean
@ConfigurationProperties ("github. client")
public AuthorizationCodeResourceDetails github() {
return new Authori zationCodeResourceDetails () ;
@Bean
@ConfigurationProperties ("gi thub . resource")

public ResourceServerProperties gi thubResource() {
return new ResourceServerProperties() ;

6.资源服务器

我们写了两个控制器来提供相应的资源。

一个控制器是MainController.java。代码如下。

@Controller
public class MainController {
@GetMapping("/")
public String root ()
return "redirect: / index";
@GetMapping ("/index")
public String index (Principal principal, Model model) {
if (principal == null ) {
return "index";
System. out.println (principal. toString()) ;
model . addAttribute ("principal", principal) ;
return "index";
@GetMapping ("/403")
public String accesssDenied() {
return "403";
}
}

在index页面如果认证成功,将会显示一些认证信息。

另一个控制器是UserContrllerjava,用来模拟用户管理的相关资源。
@RestController
@RequestMapping("/")
public class UserController
/**
*查询所用用户
return
@GetMapping(" /users")
CPreAuthorize ("hasAuthority('ROLE_ USER')") // 指定角色权限才能操作方法
public ModelAndView list (Model model) {
List<User> list = new ArrayList<>() ; //当前所在页面数据列表
list. add (new User ("waylau",29)) ;
list.add (new User("老卫",30)) ;
model. addAttribute ("title", "用户管理") ;
model. addAttribute ("userList", list) ;
return new ModelAndView ("users/list", "userModel", model) ;
}

7.前端页面

页面主要是采用Thymeleaf及Bootstrap来编写的。

首页用于显示用户的基本信息。
<body>
<div class="container">
<div class="mt-3">
<h2>He1l1o Spring Security</h2>
</div>
<div sec: authori ze=" isAuthenticated()" th:if="${principal}" th:-
object="${principal}">
<p>已有用户登录</p>
<p>登录的用户为: <span sec: authentication="name"></span></p>
<p>用户权限为: <span th: text="* {userAuthentication. authori-
ties}"></span></p>
<p>用户头像为: <img alt="" class="avatar width-full rounded-
2" height="230"
th:src="* {userAuthentication.details.avatar_ url}"
width="230"></p>
</div>
<div sec: authori ze="i sAnonymous () ">
<p>未有用户登录</p>
</div>
</div>
</body>
用户管理界面显示用户的列表。
<body>
<div class="container">
<div class="mt-3">
<h2 th:text="$ {userModel. title} ">Welcome to waylau. com</h2>
</div>
<table class="table table-hover">
<thead>
<tr>
<td>Age</td>
<td>Name</td>
<td sec :authorize="hasRole (' ADMIN') ">Operation</td>
</tr>
</ thead>
<tbody>
<tr th:if="$ {userModel.userList.size() } eq 0">
<td colspan="3">没有用户信息! ! </td>
</tr>
<tr th:each="user : $ {userModel .userList}">
<td th:text="${user.age}">11</td>
<td th: text="$ {user . name}">waylau</a></td>
<td sec:authorize="hasRole(' ADMIN')">
<div >
我是管理员
</div>
</td>
</tr>
</ tbody>
</ table>
</body>

8.运行效果

图3-3展示的是没有授权访问首页。

当我们单击“登录”按钮时,会重定向到GitHub,登录界面并进行授权,如图3-4所示。

图3-5展示的是授权后的首页。

授权后就能进入用户管理界面,如图3-6所示。

9.注册GitHub应用

如果需要注册,请根据下面的流程来生成Client ID和Client Secret。

访问htpt:p:/itb.co/ettings/applications/new,注册应用,生成客户端ID和密码。比如,

Client ID : ad2abbc1 9b6c5f0ed117
Client Secret : 2 6db88a4dfc34cebaf196e68761c1294ac4ce265

将客户端ID和密码写入程序配置即可。图3-7展示了注册应用信息的界面。

本篇讲述的内容是基于Spring Security实现的基本认证及OAuth2,喜欢的朋友可以关注关注一下!

感谢大家的支持!!!

下篇给大家介绍的内容是如何在 Spring Boot应用中,实现跨域访问资源~~

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码