1つは、SpringSecurityフレームワークです。
1.フレームワークの概要
公式紹介: Spring Securityは、強力で高度にカスタマイズ可能な認証およびアクセス制御フレームワークです。これは、Springベースのアプリケーションを保護するための事実上の標準です。Spring Securityは、Javaアプリケーションの認証と承認の提供に重点を置いたフレームワークです。すべてのSpringプロジェクトと同様に、Spring Securityの真の力は、カスタム要件を満たすように簡単に拡張できることです。
Spring Securityは、Springベースのエンタープライズアプリケーションシステムに宣言型のセキュリティアクセス制御ソリューションを提供するセキュリティフレームワークです(つまり、アクセス許可を制御します)。アプリケーションセキュリティには、ユーザー認証(Authentication)とユーザー認証(Authorization)が含まれます。 2つの部分。Spring Securityの主なコア機能は認証と承認であり、すべてのアーキテクチャもこれら2つのコア機能に基づいて実装されています。
ユーザー認証とは、ユーザーがシステムの法的な対象であるかどうか、つまり、ユーザーがシステムにアクセスできるかどうかを確認することです。ユーザー認証では通常、ユーザーがユーザー名とパスワードを入力する必要があります。システムは、ユーザー名とパスワードを確認することにより、認証プロセスを完了します。
ユーザー認証とは、ユーザーが特定の操作を実行する権限を持っているかどうかを確認することです。システムでは、ユーザーごとに権限が異なります。たとえば、ファイルの場合、一部のユーザーはそのファイルを読み取ることしかできず、一部のユーザーはそれを変更できます。一般的に、システムはさまざまなユーザーにさまざまな役割を割り当て、各役割は一連の権限に対応します。
特徴:
- 認証と承認のための包括的でスケーラブルなサポート
- セッションの固定、クリックジャック、クロスサイトリクエストの偽造などの攻撃を防止します
- サーブレットAPIの統合
- Spring WebMVCとのオプションの統合
2.フレームワークの原則
Webリソースを保護するための最良の方法はフィルターであり、メソッド呼び出しを保護するための最良の方法はAOPです。したがって、Spring Securityは、さまざまなインターセプターを使用して、ユーザーを認証するときにアクセス許可へのアクセスを制御し、セキュリティを実現するためのアクセス許可を付与します。
Spring Securityフレームワークの主なフィルター(フィルター):
Webリソースを保護するための最良の方法はフィルターであり、メソッド呼び出しを保護するための最良の方法はAOPです。したがって、Spring Securityは、さまざまなインターセプターを使用して、ユーザーを認証するときにアクセス許可へのアクセスを制御し、セキュリティを実現するためのアクセス許可を付与します。
Spring Securityフレームワークの主なフィルター(フィルター):
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CorsFilter
- LogoutFilter
- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- AnonymousAuthenticationFilter
- SessionManagementFilter
- ExceptionTranslationFilter
- FilterSecurityInterceptor
- UsernamePasswordAuthenticationFilter
- BasicAuthenticationFilter
Spring Securityフレームワークのコアコンポーネント:
- SecurityContextHolder:SecurityContextへのアクセスを提供します
- SecurityContext:認証オブジェクトおよび必要になる可能性のあるその他の情報を保持します
- 複数のAuthenticationProviderを含むことができるAuthenticationManager
- ProviderManagerオブジェクトは、AuthenticationManagerインターフェイスの実装クラスです。
- AuthenticationProviderクラスは主に、認証操作を実行するためにauthenticate()メソッドを呼び出すための認証操作に使用されます。
- 認証:Springセキュリティモードの認証対象
- GrantedAuthority:現在のユーザーの承認情報を含む、認証サブジェクトのアプリケーションレベルの承認。通常はロールで表されます。
- UserDetails:認証オブジェクトを構築するために必要な情報。カスタマイズ可能であり、DBにアクセスして取得する必要がある場合があります。
- UserDetailsService:usernameを介してUserDetailsオブジェクトを構築し、loadUserByUsernameを介してuserNameに従ってUserDetailオブジェクトを取得します(データベース、xml、キャッシュなどを介して、ここで独自のビジネスに基づいて実装をカスタマイズできます)
二、SpringBoot統合春のセキュリティ
1.プロジェクト環境
(1)JDKバージョン:1.8
(2)スプリングブーツ:2.1.2.RELEASE
(3)春のセキュリティ5.1.3
(4)IntelliJ IDEA 2016.3.4
2.データベースとテーブルを作成します
テーブル作成ステートメントは次のとおりです。ユーザーに対応するパスワードはmd5で暗号化されています。
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(255) DEFAULT NULL COMMENT '姓名',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
`roles` varchar(255) DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='用户表';
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'ouyang', 'bbd126f4856c57f68d4e30264da6a4e6', 'ROLE_ADMIN,ROLE_USER');
INSERT INTO `user` VALUES ('2', 'admin', 'bbd126f4856c57f68d4e30264da6a4e6', 'ROLE_ADMIN');
INSERT INTO `user` VALUES ('3', 'user', 'bbd126f4856c57f68d4e30264da6a4e6', 'ROLE_USER');
3.依存関係を追加し、ymlを構成します
pom.xmlに依存します:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.oycbest</groupId>
<artifactId>springsecuritytest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springsecuritytest</name>
<description>springsecurity 安全认证框架实战项目</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<!--Spring Boot热加载 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!--Spring Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--JDBC-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.29</version>
</dependency>
<!--spring-data-jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml配置:
server:
port: 8082
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/springsecurity?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8
username: ouyangcheng
password: 123456
driver-class-name: com.mysql.jdbc.Driver
druid:
initialSize: 1
minIdle: 1
maxActive: 50
maxWait: 6000
timeBetweenEvictionRunsMillis: 6000
minEvictableIdleTimeMillis: 30000
testWhileIdle: true
testOnBorrow: true
testOnReturn: true
validationQuery: SELECT 1 from dual
connectionProperties: config.decrypt=false
4.スプリングセキュリティ構成ファイルを作成します
package com.oycbest.config;
import com.oycbest.domain.User;
import com.oycbest.service.PasswordEncoder;
import com.oycbest.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.annotation.Resource;
/**
* @Author: oyc
* @Date: 2019/1/29 13:45
* @Description:
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserService<User> userService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//允许基于HttpServletRequest使用限制访问
http.authorizeRequests()
//不需要身份认证
.antMatchers("/", "/home","/toLogin","/**/customer/**").permitAll()
.antMatchers("/js/**", "/css/**", "/images/**", "/fronts/**", "/doc/**", "/toLogin").permitAll()
.antMatchers("/user/**").hasAnyRole("USER")
//.hasIpAddress()//读取配置权限配置
.antMatchers("/**").access("hasRole('ADMIN')")
.anyRequest().authenticated()
//自定义登录界面
.and().formLogin().loginPage("/toLogin").loginProcessingUrl("/login").failureUrl("/toLogin?error").permitAll()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and().exceptionHandling().accessDeniedPage("/toLogin?deny")
.and().httpBasic()
.and().sessionManagement().invalidSessionUrl("/toLogin")
.and().csrf().disable();
}
}
5.UserDetialsServerクラスを実装するUserServiceを作成します
このクラスは主にloadUserBynameメソッドを実装し、サービス、リポジトリ、またはマッパーインターフェイスをこのクラスに挿入して、メソッド内のユーザー名に従ってユーザーを取得し、ユーザーのアクセス許可を取得できます。ユーザー名を使用してデータベースにクエリを実行します。ユーザーが見つからない場合、ログインは失敗し、元のWebページに残ります。ユーザーが見つかった場合、ユーザーのアカウントパスワードと、見つかったユーザーのすべての権限がセキュリティユーザーにカプセル化されます。クラスで返されます(取得されたフォームはorg.springframework.security.core.userdetails.User@c41325a7:ユーザー名:ouyang;パスワード:[PROTECTED];有効:true; AccountNonExpired:true; credentialsNonExpired:true; AccountNonLocked:true;付与された権限:ROLE_ADMIN、ROLE_USER)、セキュリティはフロントデスクから送信されたパスワードと見つかったパスワードを比較して、ログインが成功したかどうかを確認し、失敗は元のWebページに残ります。このステップはフレームワーク自体によって解決されます。判断する必要はありません。ユーザーに戻ります。
ここにUserRepositoryを直接挿入し、UserRepositoryを使用してユーザー情報と権限を直接取得します。UserRepositoryについて質問がある場合は、Spring Boot紹介シリーズ8の前のセクションを参照してください(SpringBootはSpringData JPAを統合してMysqlデータベースを操作します):https://blog.csdn.net/u014553029 / article / details / 86662518
package com.oycbest.service;
import com.oycbest.domain.User;
import com.oycbest.repository.UserRepository;
import org.apache.commons.lang3.StringUtils;
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 javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: oyc
* @Date: 2019/1/29 14:19
* @Description: 用户服务类
*/
@Service
public class UserService<T extends User> implements UserDetailsService {
@Resource
private UserRepository<User> repository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
User user = repository.findByUserName(username);
if (user == null) {
throw new UsernameNotFoundException("用户名不存在");
}
//用户权限
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
if (StringUtils.isNotBlank(user.getRoles())) {
String[] roles = user.getRoles().split(",");
for (String role : roles) {
if (StringUtils.isNotBlank(role)) {
authorities.add(new SimpleGrantedAuthority(role.trim()));
}
}
}
return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), authorities);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
6.その他
login.html、MD5Util、およびPasswordEncoderが使用され、コードは次のとおりです。
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}" style="color: red;">
Invalid username and password.
</div>
<div th:if="${param.logout}" style="color: red;">
You have been logged out.
</div>
<form th:action="@{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="submit"/> <input type="reset" value="reset"/></div>
</form>
<p>Click <a th:href="@{/home}">here</a> go to home page.</p>
</body>
</html>
MD5Util.java
package com.oycbest.util;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @Author: oyc
* @Date: 2018/12/3 11:11
* @Description: MD5加密工具
*/
public class MD5Util {
public static final int time = 5;
public static final String SALT = "springsecurity";
/**
* 密码加密方法
*
* @param password
* @return
*/
public static String encode(String password) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
}
try {
for (int i = 0; i < time; i++) {
byte[] bytes = digest.digest((password + SALT).getBytes("UTF-8"));
password = String.format("%032x", new BigInteger(1, bytes));
}
return password;
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
}
}
public static void main(String[] args) {
System.out.println(MD5Util.encode("123456"));
}
}
PasswordEncoder.java
package com.oycbest.service;
import com.oycbest.util.MD5Util;
/**
* @Author: oyc
* @Date: 2018/12/3 10:29
* @Description: 密码加密类
*/
public class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return MD5Util.encode((String) rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {//user Details Service验证
return encodedPassword.equals(MD5Util.encode((String) rawPassword));
}
}
3、テスト
ouayngにはすべての権限があるため、最初にユーザーouyangでログインし、adminとuserにアクセスできます。adminuserでログインすると、通常どおりadminにアクセスできますが、ユーザーパスにアクセスすると、adminユーザーにアクセス権がないため、ブロックされます。ユーザーパスの権限。
UserService中的loadUserByUsername在认证过程获取数据如下: