当前位置: 首页 > wzjs >正文

有没有专门做名片的网站盘锦威旺做网站建设

有没有专门做名片的网站,盘锦威旺做网站建设,外贸网站系统,网站建设基本步骤引言 在当今的互联网生态中,安全认证与授权机制对于保护用户数据和系统资源至关重要。OAuth2作为一种行业标准的授权框架,被广泛应用于各类Web应用、移动应用和API服务中。本文将带领读者从零开始,使用Java和Spring Security框架构建一个功能…

引言

在当今的互联网生态中,安全认证与授权机制对于保护用户数据和系统资源至关重要。OAuth2作为一种行业标准的授权框架,被广泛应用于各类Web应用、移动应用和API服务中。本文将带领读者从零开始,使用Java和Spring Security框架构建一个功能完整的OAuth2授权服务器,深入理解OAuth2的核心概念和实现细节。

OAuth2基础知识

OAuth2是什么?

OAuth2(Open Authorization 2.0)是一个开放标准的授权协议,允许第三方应用在不获取用户凭证的情况下,获得对用户资源的有限访问权限。它解决了传统认证方式中的安全隐患,如密码共享和过度授权等问题。

OAuth2的角色

OAuth2定义了四个关键角色:

  1. 资源所有者(Resource Owner):通常是用户,拥有受保护资源的实体。
  2. 客户端(Client):请求访问资源的应用程序。
  3. 授权服务器(Authorization Server):验证资源所有者身份并颁发访问令牌。
  4. 资源服务器(Resource Server):托管受保护资源的服务器,接受并验证访问令牌。

OAuth2的授权流程

OAuth2支持多种授权流程,适用于不同场景:

  1. 授权码模式(Authorization Code):最完整、最安全的流程,适用于有后端的Web应用。
  2. 简化模式(Implicit):适用于无后端的单页应用。
  3. 密码模式(Resource Owner Password Credentials):适用于高度可信的应用。
  4. 客户端凭证模式(Client Credentials):适用于服务器间通信。

项目准备

环境要求

  • JDK 11+
  • Maven 3.6+
  • Spring Boot 2.6.x
  • Spring Security 5.6.x
  • Spring Authorization Server 0.3.x

项目结构

oauth2-server/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── oauth2server/
│   │   │               ├── config/
│   │   │               ├── controller/
│   │   │               ├── entity/
│   │   │               ├── repository/
│   │   │               ├── service/
│   │   │               └── OAuth2ServerApplication.java
│   │   └── resources/
│   │       ├── templates/
│   │       ├── static/
│   │       └── application.yml
│   └── test/
├── pom.xml
└── README.md

Maven依赖配置

<dependencies><!-- Spring Boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- Spring Authorization Server --><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-authorization-server</artifactId><version>0.3.1</version></dependency><!-- Database --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- Utilities --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

实现授权服务器

步骤1:创建基础应用

首先,创建一个Spring Boot应用作为我们的起点:

package com.example.oauth2server;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class OAuth2ServerApplication {public static void main(String[] args) {SpringApplication.run(OAuth2ServerApplication.class, args);}
}

步骤2:配置数据库

application.yml中配置数据库连接:

spring:datasource:url: jdbc:h2:mem:oauth2dbdriver-class-name: org.h2.Driverusername: sapassword: passwordjpa:database-platform: org.hibernate.dialect.H2Dialecthibernate:ddl-auto: updateshow-sql: trueh2:console:enabled: truepath: /h2-console

步骤3:创建用户实体和存储

package com.example.oauth2server.entity;import lombok.Data;
import javax.persistence.*;
import java.util.Set;@Entity
@Data
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(unique = true)private String username;private String password;@ElementCollection(fetch = FetchType.EAGER)private Set<String> roles;private boolean enabled = true;
}

创建用户存储库:

package com.example.oauth2server.repository;import com.example.oauth2server.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findByUsername(String username);
}

步骤4:实现用户服务

package com.example.oauth2server.service;import com.example.oauth2server.entity.User;
import com.example.oauth2server.repository.UserRepository;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.stream.Collectors;@Service
public class UserDetailsServiceImpl implements UserDetailsService {private final UserRepository userRepository;public UserDetailsServiceImpl(UserRepository userRepository) {this.userRepository = userRepository;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),user.isEnabled(),true,true,true,user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toSet()));}
}

步骤5:配置安全设置

package com.example.oauth2server.config;import com.example.oauth2server.service.UserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;@EnableWebSecurity
@Configuration
public class SecurityConfig {private final UserDetailsServiceImpl userDetailsService;public SecurityConfig(UserDetailsServiceImpl userDetailsService) {this.userDetailsService = userDetailsService;}@Bean@Order(2)public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize ->authorize.antMatchers("/h2-console/**").permitAll().anyRequest().authenticated()).formLogin().and().csrf().ignoringAntMatchers("/h2-console/**").and().headers().frameOptions().sameOrigin();return http.build();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

步骤6:配置OAuth2授权服务器

package com.example.oauth2server.config;import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.RequestMatcher;import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;@Configuration
public class AuthorizationServerConfig {@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =new OAuth2AuthorizationServerConfigurer<>();RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();http.requestMatcher(endpointsMatcher).authorizeRequests(authorizeRequests ->authorizeRequests.anyRequest().authenticated()).csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher)).apply(authorizationServerConfigurer);return http.build();}@Beanpublic RegisteredClientRepository registeredClientRepository() {RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("client").clientSecret("$2a$10$jdJGhzsiIqYFpjJiYWMl/eKDOd8vdyQis2aynmFN0dgJ53XvpzzwC") // "secret" encoded.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).redirectUri("http://127.0.0.1:8080/login/oauth2/code/client").scope(OidcScopes.OPENID).scope("read").scope("write").build();return new InMemoryRegisteredClientRepository(registeredClient);}@Beanpublic JWKSource<SecurityContext> jwkSource() {RSAKey rsaKey = generateRsa();JWKSet jwkSet = new JWKSet(rsaKey);return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);}private static RSAKey generateRsa() {KeyPair keyPair = generateRsaKey();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();}private static KeyPair generateRsaKey() {KeyPair keyPair;try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();} catch (Exception ex) {throw new IllegalStateException(ex);}return keyPair;}@Beanpublic ProviderSettings providerSettings() {return ProviderSettings.builder().issuer("http://localhost:9000").build();}
}

步骤7:初始化测试数据

创建一个数据初始化器:

package com.example.oauth2server.config;import com.example.oauth2server.entity.User;
import com.example.oauth2server.repository.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;import java.util.Set;@Configuration
public class DataInitializer {@Beanpublic CommandLineRunner initData(UserRepository userRepository, PasswordEncoder passwordEncoder) {return args -> {User admin = new User();admin.setUsername("admin");admin.setPassword(passwordEncoder.encode("admin"));admin.setRoles(Set.of("ADMIN", "USER"));User user = new User();user.setUsername("user");user.setPassword(passwordEncoder.encode("password"));user.setRoles(Set.of("USER"));userRepository.save(admin);userRepository.save(user);};}
}

步骤8:配置应用属性

application.yml中添加服务器端口配置:

server:port: 9000

测试授权服务器

授权码流程测试

  1. 请求授权码

    访问以下URL(可以在浏览器中打开):

    http://localhost:9000/oauth2/authorize?response_type=code&client_id=client&scope=read&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/client
    

    系统会要求登录(使用我们创建的用户凭据),然后请求授权。授权后,系统会重定向到指定的URI,并附带授权码。

  2. 使用授权码获取令牌

    使用curl或Postman发送POST请求:

    curl -X POST \http://localhost:9000/oauth2/token \-H "Content-Type: application/x-www-form-urlencoded" \-H "Authorization: Basic Y2xpZW50OnNlY3JldA==" \-d "grant_type=authorization_code&code=YOUR_AUTHORIZATION_CODE&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/client"
    

    注意:YOUR_AUTHORIZATION_CODE需要替换为上一步获取的授权码。

  3. 使用访问令牌访问资源

    使用获取到的访问令牌访问受保护资源:

    curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" http://localhost:9000/api/resource
    

扩展功能

添加资源服务器

创建一个简单的资源API:

package com.example.oauth2server.controller;import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Collections;
import java.util.Map;@RestController
@RequestMapping("/api")
public class ResourceController {@GetMapping("/resource")public Map<String, Object> resource(@AuthenticationPrincipal Jwt jwt) {return Collections.singletonMap("message", "Protected resource accessed by: " + jwt.getSubject());}
}

配置资源服务器安全设置:

package com.example.oauth2server.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;@Configuration
@EnableWebSecurity
public class ResourceServerConfig {@Bean@Order(3)public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http) throws Exception {http.requestMatchers().antMatchers("/api/**").and().authorizeRequests().anyRequest().authenticated().and().oauth2ResourceServer().jwt();return http.build();}
}

实现令牌撤销

添加令牌撤销端点:

package com.example.oauth2server.controller;import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TokenController {private final OAuth2AuthorizationService authorizationService;public TokenController(OAuth2AuthorizationService authorizationService) {this.authorizationService = authorizationService;}@PostMapping("/oauth2/revoke")public void revokeToken(@RequestParam("token") String token, @RequestParam("token_type_hint") String tokenTypeHint) {OAuth2TokenType tokenType = "access_token".equals(tokenTypeHint) ? OAuth2TokenType.ACCESS_TOKEN : OAuth2TokenType.REFRESH_TOKEN;authorizationService.findByToken(token, tokenType).ifPresent(authorization -> {authorizationService.remove(authorization);});}
}

自定义授权同意页面

创建一个Thymeleaf模板用于授权同意页面:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>授权确认</title><style>body {font-family: Arial, sans-serif;max-width: 600px;margin: 0 auto;padding: 20px;}.container {border: 1px solid #ddd;border-radius: 5px;padding: 20px;margin-top: 20px;}.btn {display: inline-block;padding: 10px 15px;background-color: #4CAF50;color: white;border: none;border-radius: 4px;cursor: pointer;text-decoration: none;margin-right: 10px;}.btn-cancel {background-color: #f44336;}.scopes {margin: 15px 0;}.scope-item {margin: 5px 0;}</style>
</head>
<body><div class="container"><h1>授权请求</h1><p>客户端 <strong th:text="${clientId}"></strong> 请求访问您的账户</p><div class="scopes"><p>请求的权限范围:</p><div th:each="scope : ${scopes}" class="scope-item"><input type="checkbox" th:id="${scope}" th:name="scope" th:value="${scope}" checked /><label th:for="${scope}" th:text="${scope}"></label></div></div><form method="post" th:action="${authorizationUri}"><input type="hidden" name="client_id" th:value="${clientId}"><input type="hidden" name="state" th:value="${state}"><div><button type="submit" name="consent" value="approve" class="btn">授权</button><button type="submit" name="consent" value="deny" class="btn btn-cancel">拒绝</button></div></form></div>
</body>
</html>

创建控制器处理授权同意请求:

package com.example.oauth2server.controller;import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.security.Principal;
import java.util.Set;@Controller
public class AuthorizationConsentController {private final RegisteredClientRepository registeredClientRepository;private final OAuth2AuthorizationConsentService authorizationConsentService;public AuthorizationConsentController(RegisteredClientRepository registeredClientRepository,OAuth2AuthorizationConsentService authorizationConsentService) {this.registeredClientRepository = registeredClientRepository;this.authorizationConsentService = authorizationConsentService;}@GetMapping("/oauth2/consent")public String consent(Principal principal,Model model,@RequestParam(OAuth2ParameterNames.CLIENT_ID) String clientId,@RequestParam(OAuth2ParameterNames.SCOPE) String scope,@RequestParam(OAuth2ParameterNames.STATE) String state) {RegisteredClient client = this.registeredClientRepository.findByClientId(clientId);OAuth2AuthorizationConsent consent = this.authorizationConsentService.findById(clientId, principal.getName());Set<String> scopesToApprove = Set.of(scope.split(" "));model.addAttribute("clientId", clientId);model.addAttribute("state", state);model.addAttribute("scopes", scopesToApprove);model.addAttribute("authorizationUri", "/oauth2/authorize");return "consent";}
}

安全最佳实践

在实现OAuth2授权服务器时,应遵循以下安全最佳实践:

  1. 使用HTTPS:在生产环境中,始终使用HTTPS保护所有通信。

  2. 安全存储客户端密钥:客户端密钥应该使用强密码哈希算法(如BCrypt)进行加密存储。

  3. 实施PKCE:对于公共客户端(如SPA和移动应用),使用PKCE(Proof Key for Code Exchange)增强安全性。

  4. 限制令牌范围和生命周期:根据实际需求限制访问令牌的范围和有效期。

  5. 实施令牌撤销:提供令牌撤销机制,允许用户或管理员在需要时撤销访问权限。

  6. 监控和审计:实施日志记录和监控,以便及时发现可疑活动。

结论

通过本文,我们从零开始构建了一个功能完整的OAuth2授权服务器。我们深入了解了OAuth2的核心概念,并使用Spring Security和Spring Authorization Server实现了各种授权流程和扩展功能。

这个授权服务器可以作为您实际项目的起点,根据具体需求进行定制和扩展。随着安全需求的不断演变,持续关注OAuth2和Spring Security的最新发展,及时更新您的实现,是确保系统安全的关键。

参考资料

  • OAuth 2.0 规范
  • Spring Authorization Server 文档
  • Spring Security 文档
  • RFC 6749 - OAuth 2.0 授权框架
  • RFC 7636 - PKCE

文章转载自:

http://h0UzPXRo.mrttc.cn
http://6A42bWhW.mrttc.cn
http://zvG6HAm8.mrttc.cn
http://do7KB4SL.mrttc.cn
http://GxHq1s75.mrttc.cn
http://KIJf8iF5.mrttc.cn
http://flbIT72v.mrttc.cn
http://iIQXe8xh.mrttc.cn
http://el7ViRxM.mrttc.cn
http://qUkk5FUg.mrttc.cn
http://zil232uR.mrttc.cn
http://vlPuOlSY.mrttc.cn
http://r5HOZity.mrttc.cn
http://IsWJq6oO.mrttc.cn
http://lxYOsgSN.mrttc.cn
http://EkgHSSnv.mrttc.cn
http://1kPLzHOl.mrttc.cn
http://vhXujTWS.mrttc.cn
http://7qDvLPN6.mrttc.cn
http://AHca2s4i.mrttc.cn
http://4qRFpHnf.mrttc.cn
http://nYybmzrP.mrttc.cn
http://2VPUG323.mrttc.cn
http://pPjwlltE.mrttc.cn
http://pdwQ76pu.mrttc.cn
http://hgj9b8UQ.mrttc.cn
http://pyvzdqCs.mrttc.cn
http://FxnDyR1q.mrttc.cn
http://l1A3eHD0.mrttc.cn
http://xo9wDPQX.mrttc.cn
http://www.dtcms.com/wzjs/738201.html

相关文章:

  • 太原推广型网站开发阿里巴巴网站策划书
  • 旅游网站 源码 织梦做网站需要准备资料
  • 什么程序做网站学校官方网站建设
  • 有后台的网站模板管理咨询公司起名
  • 市场推广渠道有哪些和平网站建设优化seo
  • 贵阳建网站公司wordpress广告图片自动轮播代码
  • 网站建设与规划论文苏州电商网站建设
  • 怎么自己做影视网站wordpress写文章
  • 做宽屏网站网站建设算不算固定资产
  • 网易做相册的网站云南网站制作
  • 网站建设是属现代服务吗咋样做网站
  • 四川南充网站建设网站销售系统怎么做
  • 前端怎么做网站长沙网络推广招聘
  • 门户网站建设哪里有网站界面尺寸大小
  • 怎样构建网站建设网站空间怎么预算
  • 付网站建设服务费记账网站定制公司哪家最权威
  • 外贸网站海外推广网站策划主题
  • 中国工信部网站备案做虚拟币网站需要什么手续
  • 遵义网站制作报价建设seo网站
  • 网站公网安备链接怎么做自己做网站好还是凡科
  • 公司有网站域名,如何做网站代码编写网站
  • 做网站的基本条件企业运营管理名词解释
  • 银医网站建设方案wordpress 截取
  • 天水 网站建设到国外网站上做兼职翻译
  • 网站左悬浮代码网站维护管理
  • ui设计 国外网站山东查询网站备案
  • 自己怎么做机构网站哈尔滨市香坊区建设局网站
  • 三合一网站建设方案不让在建设门户网站
  • 如何创建自己的公司网站电脑和手机同步编辑wordpress
  • 去国外做网站wordpress 需要授权吗