一. 准备数据库
二. 我的login.html登录页面
三. 配置自定义表单
设置登录成功与失败的页面
在上一个文章的基础至上进行添加内容完成根据数据库认证操作
*.自定义表单
分别是 认证页面 认证成功页面 认证失败页面
写完这个地方可以访问 http://localhost:8080/login.html 自己的登录页面这个路径来查看是否配置成功
http.formLogin()
.loginPage("/login.html").permitAll()// 登录的页面是login.html
.defaultSuccessUrl("/home.html") // 访问输入login.html 成功之后默认跳转的页面
.failureUrl("/fail.html") // 访问失败的跳转页面
.usernameParameter("uname") // 默认的name值为username 改为自己想改的 在login.html页面
.passwordParameter("pwd") //默认的password值为password 改为自己想改的 在login.html页面
.loginProcessingUrl("/mylogin").permitAll()
;
四. 配置自定义用户
因为需要基于数据库用户进行登录所以需要进行配置用户信息---数据库在最上方
1. 设置加密密码
添加一个测试类
首先 加jar包
<!-- 加test测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.7.17</version> </dependency>
创建测试类
2. 设置配置类加密密码
在配置类里面添加一个@Bean
@Bean 与 @Compponent 有什么不同
@Compponent 放在类上使用
@Bean 可以放在方法上使用
在 configure(AuthenticationManagerBuilder auth) 部分进行对密码加密
/**
* 配置用户的信息
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 不能使用明文密码
// 配置使用的密码是什么
PasswordEncoder passwordEncoder = getPasswordEncoder();
// 不用固定密码了 下面开始从数据库查数据
String pwd = passwordEncoder.encode("dys");// 加密之后的密码
// 解析密码吗的时候 需要看你使用的加密规则 是什么 加密和解密务必使用同一套规则
System.out.println("pwd = " + pwd);
// 在内存中配置认证的信息
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)// 加密解密的规则
.withUser("dys").password(pwd).roles("admin");
}
在刚创建的测试类里进行使用
// 测试工具类
@SpringBootTest(classes = MySpringsecuity.class)
public class MyTest {
// 调用在 MySecurityConfig 里写好的密码加密 对下方密码进行加密操作
@Resource
PasswordEncoder passwordEncoder;
@Test
public void test(){
// 对下方密码进行加密操作
String pwd = "123456";
String encode = passwordEncoder.encode(pwd);
System.out.println(encode);
//加密之后: $2a$10$4nzPl.SorSWhJDm.r2WiEuGQaPlQVOOsuTE86gUKGe7P0ksQraXoy
}
}
五. 设置权限 service业务层
创建 UserServiceImpl 需要实现一个接口 名字为UserDetailService 是框架自带的一个接口
需要进行配置 配置完之后即可使用
编写配置文件
加密密码部分进行修改 加密的时候从service走一遍 到这里 service已经可以收到username名
/**
* 从数据库查询需要注入的类 当前项目只有UserServiceImpl实现了userDetailsService
* 所以理所当然注入的是当前项目只有UserServiceImpl实现了userDetailsService
*/
@Resource
private UserDetailsService userDetailsService;
/**
* 配置用户的信息
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 不能使用明文密码
// 配置使用的密码是什么
PasswordEncoder passwordEncoder = getPasswordEncoder();
// 不用固定密码了 下面开始从数据库查数据
/*String pwd = passwordEncoder.encode("dys");// 加密之后的密码
// 解析密码吗的时候 需要看你使用的加密规则 是什么 加密和解密务必使用同一套规则
System.out.println("pwd = " + pwd);
// 在内存中配置认证的信息
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)// 加密解密的规则
.withUser("dys").password(pwd).roles("admin");*/
// 通过userDetailsService从数据库查询用户信息 .passwordEncoder(passwordEncoder)配置密码不能是明文的解析器
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
六. 根据数据库进行查询
写完之后访问的路径:标题http://localhost:8080/home.html
1.加jar包
<!-- mybatis包 连接数据库--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.44</version> </dependency>
2.加application配置文件
spring: datasource: # 连接数据库 四大金刚 驱动 url 用户名 密码 url: jdbc:mysql://localhost:3306/springboottest?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true password: 123456 username: root driver-class-name: com.mysql.jdbc.Driver
3.添加实体类
4.添加Mapper层(dao层)
! ! ! 写mapper层之前不要忘了在启动类加上
@MapperScan("com.aaa.mapper")
5.编写Service层
所有注释都在代码中
package com.aaa.service;
import com.aaa.mapper.UserMapper;
import com.aaa.entity.MyUser;
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 javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* implements UserDetailsService 是SpringSecurity框架自带的接口
* 在需要认证的时候需要走这个service 需要在MyServiceConfig 里进行配置
*/
@Service
public class UserServiceImpl implements UserDetailsService {
@Resource
private UserMapper userDao;
/**
* Spring username 代表前台传过来的用户名
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 在MySecurityConfig里配置完之后这里就可以获取到用户user了
System.out.println(username);
MyUser myUser = userDao.selectAll(username);
//能获取到之后 根据username(名字)去数据库中查询
// 判断是否从数据库中查到数据 如果没有查到数据则抛出异常
if (myUser==null) {
// 如果没有查到 没有登录
System.out.println("没有这个用户");
throw new UsernameNotFoundException("没有这个用户");
}
/**
* public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
* this(username, password, true, true, true, true, authorities);
* }
* 使用这个构造方法
* 需要三个参数 String username, String password, Collection
* 第一个传账号
* 第二个传密码
* 第三个传这个用户所拥有的权限
*/
List<SimpleGrantedAuthority> list = new ArrayList<>();
/**
* 这里写菜单管理跟角色
* 角色 官方推荐 角色使用 ROLE_ 开头 后面加名字
*/
list.add(new SimpleGrantedAuthority("ROLE_ADMIN")); // 第一个角色
list.add(new SimpleGrantedAuthority("ROLE_USER")); // 第二个角色
list.add(new SimpleGrantedAuthority("menu")); // 菜单管理
// // 这里的User不是自己写的类 而是 UserDetails 里的一个实现类
return new User(myUser.getUsername(),myUser.getPwd(),list);
}
}
认证到这里已经结束
6.修改配置类
写完这里就可以运行了
详细注释代码中
7. 上方配置完登录成功之后查询用户全部信息
这里与上方浏览器的开始访问路径不同http://localhost:8080/user
查询用户全部信息一共有三种方式 编写有些许区别但是用途相同
创建一个controller层
第一种
/**
* 第一种方式
* principal 代表了用户的全部信息
* @return
*/
@GetMapping
public Principal getUser(Principal principal){
// 主题 principal代表了用户信息 里面有所有用户的信息 ---- 浏览器直接访问http://localhost:8080/user
return principal;
}
第二种
/**
* 第二种方式 从框架内获取到
* @return
*/
@GetMapping
public User getUser(){
User principal = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return principal;
}
第三种
/**
* 第三种方式 跟第二种方式想比少了中间的一串
* @param authentication
* @return
*/
@GetMapping
public User getUser(Authentication authentication){
return (User) authentication.getPrincipal();
}
七. 简单授权
1.编写Controller层
2.编写配置类
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login.html").permitAll()// 登录的页面是login.html
.defaultSuccessUrl("/home.html") // 访问输入login.html 成功之后默认跳转的页面
.failureUrl("/fail.html") // 访问失败的跳转页面
.usernameParameter("uname") // 默认的name值为username 改为自己想改的 在login.html页面
.passwordParameter("pwd") //默认的password值为password 改为自己想改的 在login.html页面
.loginProcessingUrl("/mylogin").permitAll()
;
/**
* 设置授权 除了这里设置的用户名 其他的一律不可通过 hasRole 这里不需要写Role_框架下会自动加 hasRole只能设置一个用户名
* 访问时输入的账号为UserServiceImpl中 if判断判断的""中的内容 如果这个账号有下方设置的权限则成功 没有则跳转403页面
*/
//http.authorizeRequests().antMatchers("/test").hasRole("ADMIN1");
// 与上面相同 可以设置多个用户名 主要满足其中一个即可
http.authorizeRequests().antMatchers("/test").hasAnyRole("ADMIN1","ADMIN");
// 根据菜单判断 逻辑跟上方用户名相同 都是如果能判断到就成功 不能就 403
//http.authorizeRequests().antMatchers("/test").hasAuthority("menu");
// 没有权限时登录报错403 配置403页面 设置页面 403.html
http.exceptionHandling().accessDeniedPage("/403.html");
// 除了放行之外的其他的路径全部需要认证
http.authorizeRequests().anyRequest().authenticated();
// 由于我们设置的 登录是一个html页面
http.csrf().disable();
}