上一次实现了基于内存验证 缺少了实际的可用性现在修改一下 SpringSecurity
的配置来实现基本的数据库验证
pom.xml
依赖请参考SpringSecurity入坑(一)的具体依赖这里不做修改
基于数据库做验证,主要的是构建权限验证
废话不多 XX 直接上CODE
User
用户表,基于SpringDataJpa
构建User
用户表
package com.shaojie.authority.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.persistence.*;
/**
* @author ShaoJie
* @Date 2019年11月25 17:49
* @Description:
*/
@Data
@Entity
@AllArgsConstructor
@Accessors(chain = true)
@Table(name = "user")
public class User {
/**
* 用户的自增 id
*/
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
/**
* 用户的账号
*/
@Column(name = "name")
private String name;
/**
* 用户的密码
*/
@Column(name = "password")
private String password;
/**
* 账号是否启用
*/
@Column(name = "enable")
private Boolean enable;
public User() {
}
}
Authority
权限表 保存用户的权限
package com.shaojie.authority.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.persistence.*;
/**
* @author: ShaoJie
* @data: 2020年01月06日 20:22
* @Description: 用户的权限
*/
@Data
@Entity
@AllArgsConstructor
@Accessors(chain = true)
@Table(name = "authority")
public class Authority {
/**
* 用户的自增 id
*/
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
/**
* 用户的账号
*/
@Column(name = "member_id")
private Integer memberId;
/**
* 用户的权限
*/
@Column(name = "authority")
private String authority;
public Authority() {
}
}
User
数据访问层
package com.shaojie.authority.dao;
import com.shaojie.authority.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author ShaoJie
* @Date 2019年11月25 18:46
* @Description:
*/
public interface UserRepository extends JpaRepository<User, Integer> {
/**
* 根据用户的账号查询用户
*
* @param name 用户的账号
* @return 用户信息
*/
User findUserByName(String name);
}
User
的业务逻辑层
package com.shaojie.authority.service;
import com.shaojie.authority.model.User;
/**
* @author ShaoJie
* @Date 2019年11月25 18:49
* @Description:
*/
public interface UserService {
/**
* 根据用户的账号查询用户
*
* @param name 用户的账号
* @return 用户信息
*/
User findUserByName(String name);
}
Authority
的业务逻辑层
package com.shaojie.authority.dao;
import com.shaojie.authority.model.Authority;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author: ShaoJie
* @data: 2020年01月06日 21:10
* @Description: 权限 数据访问层
*/
public interface AuthorityRepository extends JpaRepository<Authority, Integer> {
}
Authority
的业务逻辑层
package com.shaojie.authority.service;
import com.shaojie.authority.model.Authority;
import java.util.List;
/**
* @author: ShaoJie
* @data: 2020年01月06日 21:14
* @Description: 权限的业务逻辑层
*/
public interface AuthorityService {
/**
* 获取用户的权限
*
* @param memberId 用户的 id
* @return 权限的集合
*/
List<Authority> getUserAuthority(Integer memberId);
}
Authority
的业务逻辑 impl
层
package com.shaojie.authority.service.impl;
import com.shaojie.authority.dao.AuthorityRepository;
import com.shaojie.authority.model.Authority;
import com.shaojie.authority.service.AuthorityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author: ShaoJie
* @data: 2020年01月06日 21:14
* @Description: 权限的业务逻辑层
*/
@Service
@Transactional
public class AuthorityServiceImpl implements AuthorityService {
/**
* 权限数据访问层
*/
@Autowired
private AuthorityRepository authorityRepository;
/**
* 获取用户的权限
*
* @param memberId 用户的 id
* @return 权限的集合
*/
@Override
public List<Authority> getUserAuthority(Integer memberId) {
Example<Authority> example = Example.of(new Authority()
.setMemberId(memberId));
return authorityRepository.findAll(example);
}
}
User
的业务逻辑 impl
层
package com.shaojie.authority.security;
import com.shaojie.authority.model.Authority;
import com.shaojie.authority.model.User;
import com.shaojie.authority.service.UserService;
import com.shaojie.authority.service.impl.AuthorityServiceImpl;
import lombok.extern.slf4j.Slf4j;
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.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 org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.ArrayList;
import java.util.List;
/**
* @author ShaoJie
* @Date 2019年11月26 19:48
* @Description:
*/
@Service
@Transactional
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {
/**
* 用户 业务逻辑层
*/
@Autowired
private UserService userService;
/**
* 权限 业务逻辑层
*/
@Autowired
private AuthorityServiceImpl authorityService;
/**
* 密码加密
*/
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
/**
* 加载登录 通过用户名查找用户
*
* @param userName 登录的用户名称
* @return 用户信息
* @throws UsernameNotFoundException 未找到用户登录名称信息
*/
@Transactional(readOnly = true)
@Override
public UserDetails loadUserByUsername(@RequestParam String userName) throws UsernameNotFoundException {
log.info("{ 当前登录的用户账号: {} }", userName);
User user = userService.findUserByName(userName);
List<GrantedAuthority> authorityList = new ArrayList<>();
if (user != null) {
// 权限集合 当前用户所具有的权限
authorityList = getUserAuthority(user.getId());
}
return new org.springframework.security.core.userdetails.User(user.getName(), bCryptPasswordEncoder.encode(user.getPassword()), authorityList);
}
/**
* 连接数据库 实现 读取权限集合
*
* @return 授予的权限
*/
public List<GrantedAuthority> getUserAuthority(Integer memberId) {
// 创建权限集合
List<GrantedAuthority> authorityList = new ArrayList<>();
// 读取用户的权限集合
List<Authority> userAuthority = authorityService.getUserAuthority(memberId);
for (Authority a : userAuthority) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(a.getAuthority());
authorityList.add(grantedAuthority);
}
return authorityList;
}
}
这里我直接都写在一起了 ,并没有细划分,其实这个分层不应该是这样,这里只是做基础的展示,所以可能代码上有些糙,有兴趣的自己做调整,下面就是关键的一步了,那就是构建权限验证
构建权限验证
package com.shaojie.authority.security;
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.method.configuration.EnableGlobalMethodSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author ShaoJie
* @Date 2019/10/25
*/
@Configuration
// 启动 SpringSecurity 的过滤器链
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 密码加密
*
* @return
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsServiceImpl userDetailsService() {
return new UserDetailsServiceImpl();
}
/**
* 用户详细信息 业务逻辑层
*/
@Autowired
public UserDetailsServiceImpl userDetailsService;
/**
* 授权
*
* @param auth
* @throws Exception
*/
// 代替配置文件 <security:authentication-manager></security:authentication-manager>
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 基于 数据库验证
auth.userDetailsService(userDetailsService());
}
/**
* 验证
*
* @param http
* @throws Exception
*/
// 代替配置文件 <security:http></security:http>
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// antMatchers 设置拦截的请求 hasAnyAuthority 对应的权限名称
// .hasAnyAuthority("PRODUCT_ADD") 用户所具有的权限
.antMatchers("/product/add").hasAnyAuthority("PRODUCT_ADD")
.antMatchers("/product/update").hasAnyAuthority("PRODUCT_UPDATE")
.antMatchers("/product/list").hasAnyAuthority("PRODUCT_LIST")
.antMatchers("/product/delete").hasAnyAuthority("PRODUCT_DELETE")
// permitAll 所有的权限都能访问
.antMatchers("/login").permitAll()
// .antMatchers("/**")
// fullyAuthenticated 不允许匿名用户查看
// .fullyAuthenticated()
// 设置所有的请求都必须经过验证才能访问
.anyRequest().authenticated()
.and()
// httpbasic 登录
// .httpBasic();
// 表单登录
.formLogin()
// 登录请求的页面
.loginPage("/login")
// 处理登录请求的 地址
.loginProcessingUrl("/index")
// 修改 spring 提供的 默认登陆参数
.usernameParameter("userName")
.passwordParameter("password")
.and()
// 开启记住我功能
.rememberMe()
.and()
// 开启登出
.logout()
.and()
// 禁用跨域的保护
.csrf().disable();
}
}
这里需要注意的就是 权限这里 ,现在只 先做到写死权限,系统所具有的哪些权限,这里需要在数据库中配置,后续继续整理,还需要主要的是,需要配置处理登录请求的 地址,基于上一章SpringSecurity入坑(一)页面需要做一下修改:
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>登录页面</h2>
<form th:action="@{/index}" method="post">
账号:<input type="text" name="userName" value="1591313226@163.com"><br>
密码:<input type="password" name="password" value="123456"><br>
<button type="submit">登录</button>
</form>
</body>
</html>
需要注意的是,这里的提交的 method
一定要是 post
到这基本的访问数据库,操作权限验证,就到这里,SpringSecurity
提供了很多,我们慢慢学习,尽量把这个吸收好。这条路还有很长,需要慢慢的接触,不能太过着急
我也好久没有学习了,很多东西都开始生疏了,共同进步吧,能力有限,能学多少就分享多少,一步一步走,脚踏实体一点,现在生活也过的一般,不舒服,多吃点苦吧,新一年,多加油