spring-security–基础–4.3–案例:用户登录认证(数据库用户)
代码位置
https://gitee.com/DanShenGuiZu/learnDemo/tree/master/spring-security-learn
1、介绍
通过SpringSecurity实现以下功能:
- 数据库user表有2个用户(用户密码)
- admin: admin
- user: admin
- 实现用户登录功能
2、代码
2.1、结构
2.2、依赖
<!--security begin-->
<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-thymeleaf</artifactId>
</dependency>
<!--security end-->
<!--数据库依赖 begin-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--数据库依赖 end-->
2.3、源码
UserBean
package com.feizhou.oauth.hello3.bean;
import lombok.Data;
/**
* 描述该类- JPA
*
* @author zhoufei
* @class: UserBean
* @date 2020/10/27 16:09
* @Verson 1.0 -2020/10/27 16:09
* @see
*/
@Data
public class UserBean {
private Long id;
private String userName;
private String password;
}
LoginController3
package com.feizhou.oauth.hello3.controller;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Administrator
* @version 1.0
**/
@RestController
public class LoginController3 {
@RequestMapping(value = "/login-success")
public String loginSuccess(){
return getUsername()+ " login-success 登录成功";
}
/**
* 测试资源1
*
* @return
*/
@GetMapping(value = "/admin/p1")
public String r1(){
return " /admin/p1 " + getUsername()+ "访问资源1";
}
/**
* 测试资源2
*
* @return
*/
@GetMapping(value = "/user/p2")
public String r2(){
return "/user/p2 " + getUsername()+ "访问资源2";
}
// 获取当前用户信息
private String getUsername(){
String username = null;
// 当前认证通过的用户身份
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 用户身份
Object principal = authentication.getPrincipal();
if(principal == null){
username = "匿名";
}
if(principal instanceof UserDetails){
UserDetails userDetails =(UserDetails)principal;
username = userDetails.getUsername();
} else {
username = principal.toString();
}
return username;
}
}
UserDao
package com.feizhou.oauth.hello3.dao;
import com.feizhou.oauth.hello3.bean.UserBean;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
/**
* 描述该类- JPA
*
* @author zhoufei
* @class: UserBean
* @date 2020/10/27 16:09
* @Verson 1.0 -2020/10/27 16:09
* @see
*/
@Repository
public class UserDao {
@Autowired
JdbcTemplate jdbcTemplate;
// 根据账号查询用户信息
public UserBean getUserByUsername(String username){
String sql = "select * from user where user_name = ?";
// 连接数据库查询用户
List<UserBean> list = jdbcTemplate.query(sql, new Object[] { username },
new BeanPropertyRowMapper<>(UserBean.class));
if(list != null && list.size()== 1){
return list.get(0);
}
return null;
}
}
SpringDataUserDetailsService
package com.feizhou.oauth.hello3.service;
import org.springframework.beans.factory.annotation.Autowired;
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 com.feizhou.oauth.hello3.bean.UserBean;
import com.feizhou.oauth.hello3.dao.UserDao;
/**
* @author Administrator
* @version 1.0
**/
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
@Autowired
UserDao userDao;
// 根据账号查询用户信息, 通过@Service将SpringDataUserDetailsService注入容器,通过UserDetailsService接口表明该类的类型是UserDetailsService
@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
// 将来连接数据库根据账号查询用户信息
UserBean bean = userDao.getUserByUsername(username);
if(bean == null){
// 如果用户查不到,返回null,由provider来抛出异常
return null;
}
UserDetails userDetails = User.withUsername(bean.getUserName()).password(bean.getPassword()).authorities("p1")
.build();
return userDetails;
}
}
MvcConfig3
package com.feizhou.oauth.hello3;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 视图配置
*
* @author zhoufei
* @class: MvcConfig
* @date 2020/10/24 21:03
* @Verson 1.0 -2020/10/24 21:03
* @see
*/
@Configuration
public class MvcConfig3 implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry){
//请求/ 跳转到login页面
registry.addViewController("/").setViewName("login");
//请求/login 跳转到login页面
registry.addViewController("/login").setViewName("login");
}
}
WebSecurityConfig3
package com.feizhou.oauth.hello3;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
//由于Spring boot starter自动装配机制,这里无需使用@EnableWebSecurity
//@EnableWebSecurity
@Configuration
public class WebSecurityConfig3 extends WebSecurityConfigurerAdapter {
// 密码编码器,不加密
@Bean
public PasswordEncoder passwordEncoder(){
// return NoOpPasswordEncoder.getInstance(); // 不加密
return new BCryptPasswordEncoder();// BCryptPasswordEncoder加密
}
// web url 拦截规则
@Override
protected void configure(HttpSecurity http)throws Exception {
http.authorizeRequests()
.antMatchers("/admin/p1").hasAuthority("p1")// 访问/admin/p1权限,需要有p1权限
.antMatchers("/user/p2").hasAuthority("p2")// 访问/user/p2,需要有p2权限
.anyRequest().authenticated()// 所有其他请求必须认证通过
.and().formLogin().loginPage("/login").successForwardUrl("/login-success")// 自定义登录成功的页面地址
.permitAll().and().logout().permitAll()
.and()//会话管理
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);//会话管理
}
}
application.properties
spring.datasource.url=jdbc:mysql://zhoufei.ali.db.com:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
3、表结构和数据
DROP TABLE IF EXISTS user;
CREATE TABLE user(
id bigint(12)NOT NULL AUTO_INCREMENT COMMENT '主键id',
user_name varchar(250)DEFAULT NULL COMMENT '名称',
password varchar(250)DEFAULT NULL COMMENT '密码',
PRIMARY KEY(id)
)ENGINE=InnoDB AUTO_INCREMENT=512794071417499657 DEFAULT CHARSET=utf8 COMMENT='文章表';
INSERT INTO user VALUES('1', 'user', '$2a$10$82imG0H/aJzplJsDlOsjheLRN60AGS.hH7E4kNRB/cQmgbbvD6ig6');
INSERT INTO user VALUES('6', 'admin', '$2a$10$R3sj4vOOa11CApJmGwTm7u5AhGFUToRYL3jhhW1hkmLqPts43hdhS');