- config配置
- controller层
- Mapper(Mybatis配置)
- pojo
- Service
- 工具类 MailUtil
- 前台页面
- 配置(application)
- 相关依赖
- UserRealm
package com.example.config;
import com.example.pojo.User;
import com.example.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
// 自定义的UserRealm
public class UserRealm extends AuthorizingRealm{
@Autowired
UserService userService;
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权doGetAuthorizationInfo");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// info.addStringPermission("user:add");
// 拿到当前登陆的这个对象
Subject subject = SecurityUtils.getSubject();
User currentUser = (User)subject.getPrincipal();
// 设置当前用户的权限
info.addStringPermission(currentUser.getPerms());
return info;
}
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证doGetAuthorizationInfo");
// String name = "root";
// String password = "123";
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
User user = userService.queryUserByName(usernamePasswordToken.getUsername());
if(user == null){
return null; // 抛出异常 UnknownAccountException
}
// 密码认证,shiro做
return new SimpleAuthenticationInfo(user,user.getPwd(),"");
}
}
- ShiroConfig
package com.example.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
// ShiroFilterFactoryBean 3
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
Map filterMap = new LinkedHashMap<>();
// filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
// 拥有了user:add权限才可以访问/user/add接口
filterMap.put("/user/add","perms[user:add]");
// 认证了就可以访问user下的所有接口
filterMap.put("/user/*","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
// 设置登录请求
shiroFilterFactoryBean.setLoginUrl("/toLogin");
// 设置未授权的请求
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
return shiroFilterFactoryBean;
}
// DefaultWebSecurityManger 2
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
// 创建 realm对象 需要自定义类 1
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
// shiroDialect: 用来整合shiro和thymeleaf
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
controller层
import com.example.utils.MailUtil;
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.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Test {
@RequestMapping({"/","/index"})
public String test(Model model){
model.addAttribute("msg","shiro测试");
return "index";
}
@RequestMapping("/user/add")
public String toAdd(){
return "user/add";
}
@RequestMapping("/user/update")
public String toUpdate(){
return "user/update";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("/login")
public String login(String username,String password,String code,Model model){
// 获取当前用户
Subject subject = SecurityUtils.getSubject();
// 封装用户的登陆数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Session session = subject.getSession();
String sendCode = (String) session.getAttribute("sendCode");
System.out.println("sendCode:"+sendCode);
try{
subject.login(token); // 执行登录方法,如果没有异常就说明OK了
session.setAttribute("loginUser",token.getPrincipal());
if(!sendCode.equals(code)){
model.addAttribute("msg","验证码错误");
return "login";
}
return "index";
}catch (UnknownAccountException uae) {
model.addAttribute("msg","用户名错误");
return "login";
} catch (IncorrectCredentialsException ice) {
model.addAttribute("msg","密码错误");
return "login";
}
}
// 未授权页面
@RequestMapping("/unauth")
@ResponseBody
public String toUnauthorized(){
return "未授权无法访问该页面";
}
// 注销
@RequestMapping("/user/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.removeAttribute("loginUser");
System.out.println("注销了");
return "redirect:/toLogin";
}
// 邮箱验证码发送
@RequestMapping("/sendCode")
@ResponseBody
public String sendCode(){
// 获取当前用户
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
String s = MailUtil.mail1();
session.setAttribute("sendCode",s);
return s;
}
}
Mapper(Mybatis配置)
package com.example.mapper;
import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
@Mapper
public interface UserMapper {
User queryUserByName(String name);
}
pojo
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private String pwd;
private String perms;
}
Service
package com.example.service;
import com.example.pojo.User;
import java.util.List;
public interface UserService {
User queryUserByName(String name);
}
package com.example.service;
import com.example.mapper.UserMapper;
import com.example.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userMapper;
@Override
public User queryUserByName(String name){
return userMapper.queryUserByName(name);
}
}
工具类 MailUtil
package com.example.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.Random;
@Component
public class MailUtil {
@Autowired(required = false)
private JavaMailSenderImpl mailSender;
private static MailUtil mailUtil;
@PostConstruct
public void init(){
mailUtil = this;
mailUtil.mailSender = this.mailSender;
}
public static String mail1() {
SimpleMailMessage mailMessage = new SimpleMailMessage();
Random random = new Random();
StringBuffer str = new StringBuffer();
for(int i = 0; i < 6; i++){
str.append(random.nextInt(10));
}
String s = str.toString();
System.out.println("邮箱验证码:"+s);
mailMessage.setSubject("验证码");
mailMessage.setText("您的验证码为:"+s+",如非本人操作,请忽略!请勿回复此邮箱");
// 收件人
// mailMessage.setTo("li17718541773@163.com");
mailMessage.setTo("1303205856@qq.com");
// 发件人
mailMessage.setFrom("1303205856@qq.com");
mailUtil.mailSender.send(mailMessage);
System.out.println("发送成功");
return s;
}
public void mail2() throws MessagingException {
// 复杂的邮件发送
MimeMessage mimeMessage = mailSender.createMimeMessage();
// 提供对 HTML 文本内容、图像等内联元素和典型邮件附件的支持(multipart是否支持多文本上传)
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
// 主题
helper.setSubject("黎明的黑暗");
// 正文(true表示开启html)
helper.setText("穿过黑暗时间",true);
// 附件
helper.addAttachment("2.jpg",new File("C:\Users\Lenovo\Pictures\Camera Roll\2.jpg"));
// 每次只能发给一个人
helper.setTo("lo17828541773@163.com");
// helper.setTo("1306305856@qq.com");
// 发件人
helper.setFrom("1303205856@qq.com");
mailSender.send(mimeMessage);
}
}
前台页面
1.index.html
首页
首页
2.login.html
Title
配置(application)
1.application.properties
mybatis.type-aliases-package=com.example.pojo mybatis.mapper-locations=classpath:mapper/*.xml #邮件发送配置 spring.mail.default-encoding=UTF-8 spring.mail.host=smtp.qq.com spring.mail.username= 登录邮箱 spring.mail.password=POP3/SMTP服务 spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true
1.application.yaml
spring:
datasource:
username: root
password: root
#?serverTimezone=UTC解决时区的报错
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
相关依赖
org.thymeleaf
thymeleaf-spring5
org.thymeleaf.extras
thymeleaf-extras-java8time
org.apache.shiro
shiro-spring
1.8.0
com.alibaba
druid
1.1.21
mysql
mysql-connector-java
log4j
log4j
1.2.12
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.2.2
org.projectlombok
lombok
com.github.theborakompanioni
thymeleaf-extras-shiro
2.0.0
org.springframework.boot
spring-boot-starter-mail
commons-io
commons-io
2.4



