【Shiro 自学笔记五】Spring Boot 整合 Shiro + Spring Data JPA 加密与验证

上一期我们整合了 Spring Boot,但是用的是假数据而且是明文。这一期我们将实现数据库整合和加密。

配置数据库

建立一个数据表,设立 3 个列:

  • id INT 自增主键
  • username VARCHAR(16) 非空
  • password VARCHAR(16) 非空

建表语句:

create table t_user
(
	id int auto_increment,
	username varchar(16) not null,
	password varchar(32) not null,
	constraint t_user_pk
		primary key (id)
);

编写工具类

实现一个 MD5 加密的工具类:

package org.koorye.util;

import org.apache.shiro.crypto.hash.Md5Hash;

public class Md5Util {
  public static String getMd5(String source) {
    Md5Hash md5Hash = new Md5Hash(source, "koorye_love_md5", 1024);
    return md5Hash.toHex();
  }
}

整合 Spring Data JPA

编写实体类

package org.koorye.pojo;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

import javax.persistence.*;

@NoArgsConstructor
@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "t_user")
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private int id;

  @Column(name = "username")
  private String username;

  @Column(name = "password")
  private String password;

  @Override
  public String toString() {
    return "ID: " + id + ", username: " + username + ", password: " + password;
  }
}

编写 Dao 层

package org.koorye.dao;

import org.koorye.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {

}

编写 Service 层

编写一个接口:

package org.koorye.service;

import org.koorye.pojo.User;

public interface UserService {
  void save(User user);
}

实现接口:

package org.koorye.service;

import org.koorye.dao.UserDao;
import org.koorye.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

  @Autowired
  private UserDao userDao;

  @Override
  public void save(User user) {
    userDao.save(user);
  }
}

编写控制器

  @Autowired
  private UserServiceImpl userService;

  @RequestMapping("/api/register")
  public String register(String username, String password) {
    String md5 = Md5Util.getMd5(password);
    User user = new User().setUsername(username).setPassword(md5);
    userService.save(user);
    return "Register Success!";
  }

注册测试

访问页面:http://localhost:8080/api/register?username=koorye&password=123456

用户名:koorye,密码:123456.

注册成功:

image-20200724025403749

查看数据库:

mysql> select * from t_user;
+----+----------+----------------------------------+
| id | username | password                         |
+----+----------+----------------------------------+
|  1 | koorye   | 95030fceb85deaddba97489be5968abd |
+----+----------+----------------------------------+
1 row in set (0.00 sec)

可以看到,密码成功被加密存储!

实现登录

编写 Dao 层

findById 之外的方法需要我们自行提供接口方法:

package org.koorye.dao;

import org.koorye.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
  User findByUsername(String username);
}

编写 Service 层

编写接口:

package org.koorye.service;

import org.koorye.pojo.User;

public interface UserService {
  void save(User user);

  User getUserByUsername(String username);
}

实现接口:

package org.koorye.service;

import org.koorye.dao.UserDao;
import org.koorye.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

  @Autowired
  private UserDao userDao;

  @Override
  public void save(User user) {
    userDao.save(user);
  }

  @Override
  public User getUserByUsername(String username) {
    return userDao.findByUsername(username);
  }
}

编写控制器

控制器和上一期相同:

  @RequestMapping("/api/login")
  public String login(String username, String password) {
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    subject.login(token);

    if (subject.isAuthenticated()) {
      return "Login Success!";
    } else {
      return "Login Failed!";
    }
  }

设置算法与散列

修改配置类中的 Realm:

  @Bean(name = "userRealm")
  public UserRealm userRealm() {
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    matcher.setHashAlgorithmName("md5");
    matcher.setHashIterations(1024);

    UserRealm userRealm = new UserRealm();
    userRealm.setCredentialsMatcher(matcher);

    return userRealm;
  }

加盐

修改 Realm 的登录验证。通过 Spring Data JPA 查到用户信息进行比对。

注意,要讲类添加 @Component 注解,交与 Spring 容器管理,才能自动注入。

同时,注入后会与配置类的 Bean 名字冲突,需要再修改配置类的 Bean:

package org.koorye.realms;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.koorye.pojo.User;
import org.koorye.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserRealm extends AuthorizingRealm {

  @Autowired
  private UserServiceImpl userService;

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    return null;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    User user = userService.getUserByUsername((String) authenticationToken.getPrincipal());
    if (user == null) {
      return null;
    } else {
      return new SimpleAuthenticationInfo(
          authenticationToken.getPrincipal(),
          user.getPassword(),
          ByteSource.Util.bytes("koorye_love_md5"),
          this.getName());
    }
  }
}

配置类:

  @Bean(name = "realm")
  public UserRealm userRealm() {
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    matcher.setHashAlgorithmName("md5");
    matcher.setHashIterations(1024);

    UserRealm userRealm = new UserRealm();
    userRealm.setCredentialsMatcher(matcher);

    return userRealm;
  }

  @Bean(name = "webSecurityManager")
  public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm realm) {
    DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
    defaultWebSecurityManager.setRealm(realm);
    return defaultWebSecurityManager;
  }

测试

访问页面:http://localhost:8080/api/login?username=koorye&password=123456

image-20200724031759947

用户名或密码错误:

image-20200724031822726

嗯?怎么报错了?我们修改一下 Controller:

  @RequestMapping("/api/login")
  public String login(String username, String password) {
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    try {
      subject.login(token);
    } catch (UnknownAccountException e) {
      return "Unknown username.";
    } catch (AuthenticationException e) {
      return "Unknown password.";
    }

    if (subject.isAuthenticated()) {
      return "Login Success!";
    } else {
      return "Login Failed!";
    }
  }

用户名正确,密码错误:

image-20200724032202574

用户名不存在:

image-20200724032558646
测试全部成功!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Spring Boot 2.0、Spring Data JPA、Thymeleaf和Shiro开发的后台管理系统可以实现一个功能强大且易于维护的应用程序。 这套技术栈的优势包括: 1. Spring Boot 2.0:它是一个快速构建应用程序的框架,提供自动化配置和减少样板代码的优势,使开发变得更加高效。 2. Spring Data JPA:它是一个基于JPA的持久化框架,通过简化数据库操作和提供对各种数据库的支持,大大减少了开发人员的工作量。 3. Thymeleaf:它是一个服务器端的Java模板引擎,可以直接处理HTML、XML、JavaScript、CSS和文本等内容。它具有易于学习和使用的特点,并且能够与Spring Boot实现良好的集成。 4. Shiro:它是一个功能强大且灵活的Java安全框架,可以提供认证、授权、加密和会话管理等功能。通过集成Shiro,我们可以轻松实现后台管理系统的用户认证和访问控制等安全需求。 基于这套技术栈,我们可以开发一个后台管理系统,实现用户登录、权限管理、菜单管理、角色管理、用户管理等功能。利用Spring Boot的自动化配置和快速启动特性,我们可以快速搭建项目的骨架,并集成Spring Data JPA实现数据访问,利用Thymeleaf开发可复用的页面组件,通过Shiro实现用户认证和授权。 总之,基于Spring Boot 2.0、Spring Data JPA、Thymeleaf和Shiro的后台管理系统,不仅可以极大地提高开发效率,还能够提供丰富的功能和安全性,帮助我们快速构建高质量的应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值