springboot整合shiro连接数据库
连接数据库认证实现注册和登录,注册保存到mysql密码进行md5加密和随机盐,登录连接数据库
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--JSP依赖-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!--shiro依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.1</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
</dependencies>
yarml
spring:
mvc:
view:
prefix: /
suffix: .jsp
datasource:
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: 333
url: jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8
mybatis:
mapper-locations: classpath:mapper/*.xml
logging:
level:
com.jing.mapper: debug
sql
目录结构
jsp页面
register.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>用户注册</title>
</head>
<body>
<%--公共资源--%>
<h1>注册</h1>
<form action="${pageContext.request.contextPath}/user/register" method="post">
用户名:<input type="text" name="username"><br>
密 码:<input type="text" name="password"><br>
<input type="submit" value="立即注册">
</form>
</body>
</html>
login.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<%--公共资源--%>
<h1>登录页面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">
用户名:<input type="text" name="username"><br>
密 码:<input type="text" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
index.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<%--受限资源--%>
<a href="${pageContext.request.contextPath}/user/logout">退出登录</a>
<h1>后台管理页面</h1>
<ul>
<li>
<a href="#">物流管理</a>
</li>
<li>
<a href="#">商品管理</a>
</li>
<li>
<a href="#">人员管理</a>
</li>
<li>
<a href="#">货物管理</a>
</li>
</ul>
</body>
</html>
entity实体类
package com.jing.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String salt;
}
mapper接口
package com.jing.mapper;
import com.jing.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
void save(User user);
User selectUserById(String username);
}
mapper.xml mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jing.mapper.UserMapper">
<insert id="save" parameterType="com.jing.entity.User" useGeneratedKeys="true" keyProperty="id">
insert into user values (#{id},#{username},#{password},#{salt});
</insert>
<select id="selectUserById" resultType="com.jing.entity.User" parameterType="string">
select * from user where username = #{username};
</select>
</mapper>
service接口
package com.jing.service;
import com.jing.entity.User;
public interface UserService {
void register(User user);
User selectUserById(String username);
}
serviceimpl
package com.jing.service.impl;
import com.jing.entity.User;
import com.jing.mapper.UserMapper;
import com.jing.service.UserService;
import com.jing.utils.SaltUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public void register(User user) {
String salt = SaltUtils.getSalt(8);
user.setSalt(salt);
// 在这实现 md5 + salt + hash
Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024);
user.setPassword(md5Hash.toHex());
userMapper.save(user);
}
@Override
public User selectUserById(String username) {
return userMapper.selectUserById(username);
}
}
随机盐工具类
package com.jing.utils;
import java.util.Random;
public class SaltUtils {
public static String getSalt(int n){
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijklmnopqrstuvwsyz!@#$$%^&*()0123456789-=".toCharArray();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < n; i++) {
char aChar = chars[new Random().nextInt(chars.length)];
stringBuffer.append(aChar);
}
return stringBuffer.toString();
}
}
shiroconfig
package com.jing.config;
import com.jing.shiro.realms.CustomRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
Map<String,String> filterChainDefinitionMap = new HashMap<String,String>();
filterChainDefinitionMap.put("/user/**","anon");
filterChainDefinitionMap.put("/register.jsp","anon");
// 拦截所有资源 必须通过shiro认证才可以通过
filterChainDefinitionMap.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
shiroFilterFactoryBean.setLoginUrl("/login.jsp");
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(Realm realm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
@Bean
public Realm realm(){
CustomRealm customRealm = new CustomRealm();
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("md5");
credentialsMatcher.setHashIterations(1024);
customRealm.setCredentialsMatcher(credentialsMatcher);
return customRealm;
}
}
自定义realm
package com.jing.shiro.realms;
import com.jing.entity.User;
import com.jing.service.UserService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
public class CustomRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("授权");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 主身份 用户名
String principal = (String) token.getPrincipal();
User user = userService.selectUserById(principal);
if (!ObjectUtils.isEmpty(user)){
return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
}
return null;
}
}
controller
package com.jing.contorller;
import com.jing.entity.User;
import com.jing.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 用户注册请求接口
*
* @return
*/
@PostMapping("/register")
public String register(User user) {
try {
userService.register(user);
return "redirect:/login.jsp";
} catch (Exception e) {
e.printStackTrace();
return "redirect:/register.jsp";
}
}
/**
* 登录
* @param username
* @param password
* @return
*/
@PostMapping("/login")
public String login(String username, String password) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return "redirect:/index.jsp";
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("账号错误!");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误!");
} catch (Exception e) {
e.printStackTrace();
}
return "redirect:/login.jsp";
}
/**
* 注销账号
* @return
*/
@GetMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/login.jsp";
}
}