1 pom.xml(Maven依赖文件)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.1</version>
</dependency>
<!-- swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
2 application.properties(配置文件)
设置MySQL连接配置和MyBatis配置。
#数据库连接池设置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
#mybatis的相关配置
mybatis.mapper-locations=classpath:mapper/*.xml
3 SQL
创建语句:
create table users(
username varchar(20) PRIMARY key COMMENT '用户名',
password varchar(60) comment '密码'
)
添加数据语句:
--密码123456
insert into users(username,password) values('xudongmaster','$2a$10$ky8Gyh5cjVRXnzXE4VO.wuHARs9eAF7VIvSz6R4idnrSnSl4E4pwy');
4 entity(实体类)
User.java:
package com.entity;
import lombok.Data;
import org.springframework.stereotype.Component;
@Component
@Data
public class User {
/**
* 用户名(登录)
*/
private String username;
/**
* 密码
*/
private String password;
}
5 Mapper(映射层)
UserMapper.java:
package com.mapper;
import com.entity.User;
import org.springframework.stereotype.Component;
@Component
public interface UserMapper {
/**
* 根据用户名获取用户信息
*
* @param username 用户名
* @return
*/
User getUserById(String username);
/**
* 更新用户密码
*
* @param user 用户信息
*/
void updatePassword(User user);
}
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="com.mapper.UserMapper">
<!-- 根据用户名获取用户信息 -->
<select id="getUserById" resultType="com.entity.User" parameterType="String">
select username,password
from users
where username = #{username}
</select>
<!-- 更新用户密码 -->
<select id="updatePassword" parameterType="com.entity.User">
update users
set password = #{password}
where username = #{username}
</select>
</mapper>
6 Service(业务层)
UserSevice.java:
package com.service;
import com.entity.User;
public interface UserService {
/**
* 更新用户密码
*
* @param user 用户信息
*/
String updatePassword(User user);
}
UserServiceImpl.java:
package com.service.impl;
import cn.hutool.core.util.StrUtil;
import com.entity.User;
import com.mapper.UserMapper;
import com.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
/**
* 更新用户密码
*
* @param user 用户信息
*/
@Override
public String updatePassword(User user) {
if (user==null||StrUtil.isBlank(user.getUsername()) || StrUtil.isBlank(user.getPassword())) {
return "用户名或密码为空";
}
//加密
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
//更新密码
userMapper.updatePassword(user);
return "更新密码成功";
}
}
LoginService.java:
package com.service;
import com.entity.User;
public interface LoginService {
/**
* 登录
*
* @param user 登录信息
* @return
*/
String login(User user);
}
LoginServiceImpl.java:
package com.service.impl;
import cn.hutool.core.util.StrUtil;
import com.entity.User;
import com.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Component;
@Component
public class LoginServiceImpl implements LoginService {
@Autowired
private AuthenticationManager authenticationManager;
/**
* 登录
*
* @param user 登录信息
* @return
*/
@Override
public String login(User user) {
if (user == null || StrUtil.isBlank(user.getUsername())) {
return "用户名不能为空!";
}
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
} catch (Exception e) {
if (e instanceof BadCredentialsException) {
return "用户名不存在或密码错误";
} else {
e.printStackTrace();
return e.getMessage();
}
}
return "登录成功";
}
}
7 Controller(控制层)
UserController.java:
package com.controller;
import com.entity.User;
import com.service.UserService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 更新用户密码
*
* @param user 用户信息
*/
@PostMapping("/updatePassword")
@ApiImplicitParams({
@ApiImplicitParam(name = "username", value = "用户名"),
@ApiImplicitParam(name = "password", value = "密码")
})
public String updatePassword(@RequestBody User user){
return userService.updatePassword(user);
}
}
LoginController.java:
package com.controller;
import com.entity.User;
import com.service.LoginService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/")
public class LoginController {
@Autowired
LoginService loginService;
/**
* 登录
*
* @param user 登录信息
* @return
*/
@PostMapping("/login")
@ApiImplicitParams({
@ApiImplicitParam(name = "username", value = "用户名"),
@ApiImplicitParam(name = "password", value = "密码")
})
public String login(@RequestBody User user) {
return loginService.login(user);
}
}
8 Application(应用启动类)
DemoApplication.java:
package com;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication
@MapperScan("com.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
9 Config(配置类)
SecurityConfig.java(Spring Security配置类)。
package com.config;
import com.entity.CustomPasswordEncoder;
import com.service.impl.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
/**
* 安全性设置
*
* @param httpSecurity
* @throws Exception
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// CSRF禁用
// 从Spring Security 4.0开始,默认情况下会启用CSRF保护,以防止CSRF攻击应用程序,Spring Security CSRF会针对PATCH,POST,PUT和DELETE方法进行防护。
.csrf().disable()
// 过滤请求
.authorizeRequests()
//允许匿名访问
.antMatchers("/login","/user/updatePassword").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
}
/**
* 身份认证接口
*
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
// 从数据库读取的用户进行身份认证
.userDetailsService(userDetailsService)
//加密方法(强散列哈希加密)
.passwordEncoder(new BCryptPasswordEncoder());
}
/**
* 解决 无法直接注入 AuthenticationManager
*
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
10 UserDetailsService(获取用户信息)
UserDetailServiceImpl.java:
package com.service.impl;
import cn.hutool.core.util.StrUtil;
import com.entity.LoginUser;
import com.entity.User;
import com.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
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;
@Component
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (StrUtil.isBlank(username)) {
return null;
}
User user = userMapper.getUserById(username);
if(user==null||StrUtil.isBlank(user.getUsername())){
return null;
}
return new LoginUser(username,user.getPassword());
}
}
11 UserDetails(用户信息类)
LoginUser.java:
package com.entity;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
@AllArgsConstructor
@NoArgsConstructor
public class LoginUser implements UserDetails {
private String username;
private String password;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
/**
* 账号没有过期状态(true账号没有过期,false账号已经过期)
* @return
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 账号没有锁住状态(true账号没有锁住,false账号锁住)
* @return
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 密码没有过期状态(true密码没有过期,false密码已经过期)
* @return
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 启用状态(true启用,false禁用)
* @return
*/
@Override
public boolean isEnabled() {
return true;
}
}
12 接口调试
用户登录:
修改密码: