Spring Security 使用数据库认证
在 Spring Security 中如果想要使用数据进行认证操作,有很多种操作方式,这里我们介绍使用 UserDetails 、 UserDetailsService来完成操作。
UserDetails
public interface UserDetails extends Serializable {
Collection extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
UserDetails 是一个接口,我们可以认为 UserDetails 作用是于封装当前进行认证的用户信息,但由于其是一个接口,所以我们可以对其进行实现,也可以使用Spring Security 提供的一个 UserDetails 的实现类 User 来完成操作
以下是 User 类的部分代码
public class User implements UserDetails, CredentialsContainer {
private String password;
private final String username;
private final Set authorities;
private final boolean accountNonExpired; //帐户是否过期
private final boolean accountNonLocked; //帐户是否锁定
private final boolean credentialsNonExpired; //认证是否过期
private final boolean enabled; //帐户是否可用
}
UserDetailsService
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
面将 UserDetails 与 UserDetailsService 做了一个简单的介绍,那么我们具体如何完成 Spring Security 的数据库认证操作哪,我们通过用户管理中用户登录来完成Spring Security 的认证操作。
3. 用户管理
3.1 用户登录
spring-security.xml
导入依赖
org.springframework.security
spring-security-web
${spring.security.version}
org.springframework.security
spring-security-config
${spring.security.version}
org.springframework.security
spring-security-core
${spring.security.version}
org.springframework.security
spring-security-taglibs
${spring.security.version}
配置web.xml
contextConfigLocation
classpath*:applicationContext.xml,classpath*:spring-security.xml
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
springSecurityFilterChain
/*
3.1.1. 登录页面 login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
数据 - AdminLTE2定制版 | Log in
UserInfo
package com.itheima.ssm.domain;
import java.util.List;
//与数据库中users对应
public class UserInfo {
private String id;
private String username;
private String email;
private String password;
private String phoneNum;
private int status;
private String statusStr;
private List roles;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getStatusStr() {
//状态0 未开启 1 开启
if (status == 0) {
statusStr = "未开启";
} else if (status == 1) {
statusStr = "开启";
}
return statusStr;
}
public void setStatusStr(String statusStr) {
this.statusStr = statusStr;
}
public List getRoles() {
return roles;
}
public void setRoles(List roles) {
this.roles = roles;
}
}
3.1.2.UserServiceImpl
public interface IUserService extends UserDetailsService{
}
package com.itheima.ssm.service.impl;
@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {
@Autowired
private IUserDao userDao;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
public UserInfo findById(String id) throws Exception {
return userDao.findById(id);
}
@Override
public void addRoleToUser(String userId, String[] roleIds) throws Exception {
for(String roleId:roleIds){
userDao.addRoleToUser(userId,roleId);
}
}
@Override
public List findOtherRoles(String userid) throws Exception {
return userDao.findOtherRoles(userid);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println(username);
UserInfo userInfo = null;
try {
userInfo = userDao.findByUsername(username);
// System.out.println(username);
// System.out.println(userInfo.toString());
} catch (Exception e) {
e.printStackTrace();
}
//处理自己的用户对象封装成UserDetails
User user = new User(userInfo.getUsername(), userInfo.getPassword(), userInfo.getStatus() == 0 ? false : true, true, true, true, getAuthority(userInfo.getRoles()));
return user;
}
//作用就是返回一个List集合,集合中装入的是角色描述
public List getAuthority(List roles) {
List list = new ArrayList<>();
for (Role role : roles) {
list.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
}
return list;
}
@Override
public List findAll() throws Exception{
//userDao.findAll();
return userDao.findAll();
}
@Override
public void save(UserInfo userInfo)throws Exception {
userInfo.setPassword(bCryptPasswordEncoder.encode(userInfo.getPassword()));
userDao.save(userInfo);
}
}
3.1.3.IUserDao
public interface IUserDao {
@Select("select * from user where id=#{id}")
public UserInfo findById(Long id) throws Exception;
@Select("select * from user where username=#{username}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(column = "username", property = "username"),
@Result(column = "email", property = "email"),
@Result(column = "password", property = "password"),
@Result(column = "phoneNum", property = "phoneNum"),
@Result(column = "status", property = "status"),
@Result(column = "id", property = "roles", javaType = List.class, many =
@Many(select = "com.itheima.ssm.dao.IRoleDao.findRoleByUserId")) })
public UserInfo findByUsername(String username);
}
public interface IRoleDao {
//根据用户id查询出所有对应的角色
@Select("select * from role where id in (select roleId from users_role where userId=#{userId})")
public List findRoleByUserId(String userId) throws Exception;
}
3.2 用户退出
使用 spring security 完成用户退出,非常简单
配置
在header.jsp修改
注销