1、在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"> <parent> <artifactId>kgf-java-learning</artifactId> <groupId>com.kgf.learning</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../kgf-java-learning/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.kgf.security</groupId> <artifactId>spring-security-demo</artifactId> <properties> <lombok.version>1.18.16</lombok.version> <fastjson.version>1.2.75</fastjson.version> <druid.version>1.2.2</druid.version> <mybatis-plus.version>3.4.1</mybatis-plus.version> <mysql.version>5.1.49</mysql.version> </properties> <dependencies> <!--引入mysql依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--引入mybatis-plus依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!-- 引入druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <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-test</artifactId> <scope>test</scope> </dependency> <!--lombok 用来简化实体类--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.2.11.RELEASE</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
2、在application.yaml文件中配置数据库连接
server: port: 8081 #spring: # security: # user: # name: admin # password: admin spring: datasource: url: jdbc:mysql://192.168.1.13:3306/oss?userUnicode=true&characterEncoding=UTF-8&serverTimeZone=UTC username: root password: 897570 driver-class-name: com.mysql.jdbc.Driver mybatis-plus: #注意:延迟加载不能在开启debug后,不能点开list信息,甚至不能把鼠标移到上面。否则在debug下会默认执行关联查询。 mapper-locations: classpath:/mappers/**/*.xml type-aliases-package: com.kgf.security
3、启动类SecurityApplication
package com.kgf.security; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan(value = "com.kgf.security.mapper") @SpringBootApplication public class SecurityApplication { public static void main(String[] args) { SpringApplication.run(SecurityApplication.class,args); } }
4、自定义的MyUserDetailsService
package com.kgf.security.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.kgf.security.mapper.UsersMapper; import com.kgf.security.model.Users; import org.springframework.security.core.GrantedAuthority; 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 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; /*** * spring security查询用户的时候会自动到这个类中去查找 */ @Service("userDetailsService") public class MyUserDetailsService implements UserDetailsService { @Resource private UsersMapper usersMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { QueryWrapper<Users> usersQueryWrapper = new QueryWrapper<>(); usersQueryWrapper.eq("username",username); Users users = usersMapper.selectOne(usersQueryWrapper); if (users==null){ throw new UsernameNotFoundException("用户名不存在!"); } //这里我们就不去查询数据库了,直接new一个对象 List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); return new User(username,users.getPassword(),authorityList); } }
5、创建UsersMapper
package com.kgf.security.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.kgf.security.model.Users; public interface UsersMapper extends BaseMapper<Users> { }
6、创建Users实体类
package com.kgf.security.model; import lombok.Data; @Data public class Users { private Integer id; private String username; private String password; }
7、创建SecurityConfig配置类
package com.kgf.security.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.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; /*** * 设置登录的用户 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //这是使用内存的方式 // BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); // String password = encoder.encode("123456"); // auth.inMemoryAuthentication().withUser("test").password(password).roles("admin"); //下面使用自定义接口实现类从数据库查询 auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/login.html")//登录页面设置 .loginProcessingUrl("/user/login")//登录访问路径,这个不需要自己写controller,配置即可,这个是spring security自动完成 .defaultSuccessUrl("/test/index").permitAll()//登录成功之后跳转的路径 .and().authorizeRequests() .antMatchers("/","/test/hello","/user/login").permitAll()//设置这些路径可以直接访问,不需要认证 .anyRequest().authenticated() .and().csrf().disable();//关闭csrf防护 } /*** * 注入PasswordEncoder到spring中 * @return */ @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }
8、创建TestController
package com.kgf.security.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("test") @RestController public class TestController { @RequestMapping("hello") public String test(){ return "hello security"; } @RequestMapping("index") public String index(){ return "hello index"; } }
9、创建我们的login.html
<!DOCTYPE html> <!-- 需要添加 <html xmlns:th="http://www.thymeleaf.org"> 这样在后面的th标签就不会报错 --> <html xmlns:th="http://www.thymeleaf.org"> <head lang="en"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>xx</title> </head> <body> <h1>表单提交</h1> <!-- 表单提交用户信息,注意字段的设置,直接是*{} --> <form action="/user/login" method="post"> <input type="text" name="username" /> <input type="text" name="password" /> <input type="submit" /> </form> </body> </html>
注意:这里面的用户名和密码必须是username和password,因为在spring security中是写死的,在spring security中存在一个UsernamePasswordAuthenticationFilter拦截器,如下:
10、插入数据库数据
11、测试
1)首先我们访问一下不需要认证的接口/test/hello
没问题,直接访问
2)我们访问一下不需要认证的接口/test/index接口,应该被拦截直接跳转到登录页面
输入我们数据库的用户名和密码:
成功!