前言
实现spring security 从数据库读取用户信息验证登录,仅仅能用,不含前端。
配置
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>
<groupId>org.example</groupId>
<artifactId>spring-security-learning</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>spring-security-02</module>
<module>spring-security-01</module>
<module>spring-security-03</module>
<module>spring-security-04</module>
</modules>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</project>
application.properties
#spring.datasource.name=mysql
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowMultiQueries=true
spring.datasource.username=xxxxxx
spring.datasource.password=xxxxxx
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sample.dao.entity.UserPattern">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="org.sample.dao.entity.UserPattern">
<id column="id" property="id" />
<result column="username" property="username" />
<result column="passwd" property="passwd" />
<result column="enabled" property="enabled" />
<result column="account_non_expired" property="account_non_expired" />
<result column="account_non_locked" property="account_non_locked" />
<result column="credentials_non_expired" property="credentials_non_expired" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, username, passwd, enabled, account_non_expired, account_non_locked, credentials_non_expired
</sql>
</mapper>
数据库
在mysql中创建 database 命名为test,创建数据表名为 h_user:
CREATE TABLE `h_user` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(255) NOT NULL,
`passwd` varchar(255) NOT NULL,
`enabled` tinyint(1) NOT NULL,
`account_non_expired` tinyint(1) NOT NULL,
`account_non_locked` tinyint(1) NOT NULL,
`credentials_non_expired` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
插入数据如下:
编码
启动类
MainApplication.java
package org.sample;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("org.sample.dao.mapper")
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
dao.entity
UserPattern.java
package org.sample.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
/**
* 测试用entity
*
* @author
* @since 2022-05-09
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@TableName(value = "test.h_user")
public class UserPattern implements Serializable {
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户名 userName
*/
@TableField(value = "username")
private String username;
/**
* 密码 password
*/
@TableField(value = "passwd")
private String password;
@TableField(value = "enabled")
private int enabled;
@TableField(value = "account_non_expired")
private int accountNonExpired;
@TableField(value = "account_non_locked")
private int accountNonLocked;
@TableField(value = "credentials_non_expired")
private int credentialsNonExpired;
}
controller
HelloController.java
package org.sample.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/sayHello")
public String sayHello(){
return "十年生死两茫茫,不思量,自难忘----苏轼,hello";
}
}
dao.mapper
UserServiceMapper.java
package org.sample.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.sample.dao.entity.UserPattern;
/**
*
* @author
* @since 2022-05-09
*/
public interface UserServiceMapper extends BaseMapper<UserPattern> {
}
service
UserService.java
package org.sample.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.sample.dao.entity.UserPattern;
/**
*
* @author
* @since 2022-05-09
*/
public interface UserService extends IService<UserPattern> {
UserPattern loadByUserName(String username);
}
UserServiceImpl.java
package org.sample.service.Impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.sample.dao.entity.UserPattern;
import org.sample.dao.mapper.UserServiceMapper;
import org.sample.service.UserService;
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.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.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserServiceImpl extends ServiceImpl<UserServiceMapper, UserPattern> implements UserService, UserDetailsService {
@Autowired
private UserServiceMapper userServiceMapper;
/**
* 方法一
* auth.userDetailsService(userDetailsService())
* @param username
* @return
*/
@Override
public UserPattern loadByUserName(String username) {
List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
.likeLeft(UserPattern::getUsername, username)
.likeRight(UserPattern::getUsername, username)
);
UserPattern userPattern = userPatterns.get(0);
return userPattern;
}
/**
* 方法二
* auth.userDetailsService(userDetailsService)
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
.likeLeft(UserPattern::getUsername, username)
.likeRight(UserPattern::getUsername, username)
);
UserPattern userPattern = userPatterns.get(0);
// 如果查不到用户名,这里可以抛出UsernameNotFoundException异常
// 根据username查询权限,这里假设从任意位置查到权限是auth
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("auth"));
return new User(userPattern.getUsername(), userPattern.getPassword(), true, true, true, true, authorities);
}
}
config
SecurityConfig.java
package org.sample.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.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.GrantedAuthority;
import org.sample.dao.entity.UserPattern;
import org.sample.service.UserService;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private UserDetailsService userDetailsService;
/**
* PasswordEncoder 是密码加密接口,因为我们是循序渐进的,我这里先用无加密实例
* @return
*/
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
/**
* 方法二:
* auth.userDetailsService(userDetailsService)
* 实现configure(AuthenticationManagerBuilder auth)配置方法
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService) //自定义构建
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
/**
* 方法一
* auth.userDetailsService(userDetailsService())
*/
// @Bean
// public UserDetailsService userDetailsService(){
// return new UserDetailsService() {
// // username是用户登录时填的用户名
// public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// UserPattern user = new UserPattern();
// user.setUsername("mike");
// user.setPassword("123456");
// try {
// user = userService.loadByUserName(username);
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// // 如果查不到用户名,这里可以抛出UsernameNotFoundException异常
// // 根据username查询权限,这里假设从任意位置查到权限是auth
// List<GrantedAuthority> authorities = new ArrayList<>();
// authorities.add(new SimpleGrantedAuthority("auth"));
// // User是系统自带的UserDetails实现类,4个状态其中一个为false就会抛异常
// return new User(user.getUsername(), user.getPassword(), true, true, true, true, authorities);
// }
// };
// }
/**
* 通过HttpSecurity 对象,获取到表单登录配置对象,修改对应的用户名和密码参数名称,即可完成自定义用户名和密码参数名称
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
.successForwardUrl("/home")
.permitAll()
.and()
.csrf().disable()
;
}
}
运行
运行MainApplication.java
postman尝试登录:
404没事,调用接口试试看:
成功~
参考
https://blog.csdn.net/qq_35872777/article/details/117361044
https://wavefar.blog.csdn.net/article/details/116204048
https://blog.csdn.net/huangxuanheng/article/details/119119532
https://blog.51cto.com/u_9806927/3217224
|