Spring Security实战小例子
主要项目结构如下
说明
- pom.xml 主要包含jpa ,web,mysql,lombok,security等模块;
- User.java 实体类;
- UserRepository.java 具体数据操作类;
- CustomUserDetailsService.java UserDetailsService实现类,用于装载用户信息;
- SecurityConfiguration.java 认证和权限控制配置类;
- AdminTestController,ProductTestController 访问入口控制器;
实现代码
- 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.2.5.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
- application.properties
######################## common config : ########################
spring.application.name=demo
server.port=8081
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
#-------------- spring cloud access&secret config --------------
# 你可以在https://usercenter.console.aliyun.com/#/manage/ak查看自己的access-key&secret-key
spring.cloud.alicloud.access-key=****
spring.cloud.alicloud.secret-key=****
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
jpa.properties.hibernate.hbm2ddl.auto=create
jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
jpa.properties.hibernate.format_sql=true
jpa.show-sql=true
- User.java
package com.example.demo.model;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.Id;
@Entity
@Data
public class User implements java.io.Serializable{
@Id
@Column
private Long id;
@Column
private String login;
@Column
private String password;
@Column
private String role;
}
- UserRepository.java
package com.example.demo.inter;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.demo.model.User;
@Repository
public interface UserRepository extends JpaRepository <User,String>{
User findOneByLogin(String login);
}
- CustomUserDetailsService.java
package com.example.demo.service;
import com.example.demo.inter.UserRepository;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.Component;
import java.util.ArrayList;
import java.util.Collection;
@Component("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
UserRepository userRepository;
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
// 1. 查询用户
User userFromDatabase = userRepository.findOneByLogin(login);
if (userFromDatabase == null) {
//log.warn("User: {} not found", login);
throw new UsernameNotFoundException("User " + login + " was not found in db");
//这里找不到必须抛异常
}
// 2. 设置角色
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(userFromDatabase.getRole());
grantedAuthorities.add(grantedAuthority);
return new org.springframework.security.core.userdetails.User(login,
userFromDatabase.getPassword(), grantedAuthorities);
}
}
- SecurityConfiguration.java
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService ;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/product/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().and()
.csrf().disable()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)// 设置自定义的userDetailsService
.passwordEncoder(passwordEncoder());
/*auth
.inMemoryAuthentication()
.withUser("admin1")
.password("admin1")
.roles("ADMIN", "USER")
.and()
.withUser("user1").password("user1")
.roles("USER");*/
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public static void main(String[] args) {
PasswordEncoder encode = new BCryptPasswordEncoder();
CharSequence cs="admin";
System.out.println(encode.encode(cs));
}
}
- AdminTestController.java
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/admin")
public class AdminTestController {
@RequestMapping("/home")
@ResponseBody
public String productInfo(){
return " admin home page ";
}
}
- ProductTestController.java
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/product")
public class ProductTestController {
@RequestMapping("/info")
@ResponseBody
public String productInfo(){
return " some product info ";
}
}
- DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- test.sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`login` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`role` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'user1', '$2a$10$ouFbu7.Y73xRh6LPJH09BumswtdzpWBX67tIZCsdUgkk9UapTU6NK', 'ROLE_USER');
INSERT INTO `user` VALUES ('2', 'admin', '$2a$10$ouFbu7.Y73xRh6LPJH09BumswtdzpWBX67tIZCsdUgkk9UapTU6NK', 'ROLE_ADMIN');
SET FOREIGN_KEY_CHECKS = 1;
演示
-
访问http://localhost:8081/product/info,账号密码:user1/admin
-
访问http://localhost:8081/admin/home
-
user访问admin/home