导入依赖(pom.xml)

 <!--整合shiro安全框架-->
  <dependency>
   <groupid>org.apache.shiro</groupid>
   <artifactid>shiro-spring</artifactid>
   <version>1.4.0</version>
  </dependency>
  <!--集成jwt实现token认证-->
  <dependency>
   <groupid>com.auth0</groupid>
   <artifactid>java-jwt</artifactid>
   <version>3.2.0</version>
  </dependency>

在 springboot 项目配置 config 包下创建 shiroconfig 配置类

@configuration
public class shiroconfig {

 /**
  * shirofilterfactorybean
  * <p>
  * anon:无需认证就可以访问
  * authc:必须认证才能访问
  * user:必须拥有 记住我 功能才能用
  * perms:拥有对某个资源的权限能访问
  * role:拥有某个角色权限能访问
  */
 @bean
 public shirofilterfactorybean getshirofilterfactorybean(@qualifier("securitymanager") defaultwebsecuritymanager defaultwebsecuritymanager) {
  shirofilterfactorybean factorybean = new shirofilterfactorybean();
  // 设置安全管理器
  factorybean.setsecuritymanager(defaultwebsecuritymanager);
  // 添加shiro的内置过滤器
  map<string, string> filtermap = new linkedhashmap<>();
  // 放行不需要权限认证的接口
  // 网站首页
  filtermap.put("/", "anon");
  filtermap.put("/index", "anon");
  filtermap.put("/index.html", "anon");
  // 不验证跳转接口
  filtermap.put("/into/**", "anon");

  // 需要权限认证的接口
  // 验证跳转接口
  filtermap.put("/verifyinto/**", "authc");
  
  factorybean.setfilterchaindefinitionmap(filtermap);

  // 访问没有授权的资源
  factorybean.setloginurl("redirect:/into/login");
  // 设置无权限时跳转的url
  factorybean.setunauthorizedurl("redirect:/into/login");

  return factorybean;
 }

 /**
  * 管理shiro的生命周期
  */
 @bean("lifecyclebeanpostprocessor")
 public lifecyclebeanpostprocessor lifecyclebeanpostprocessor() {
  return new lifecyclebeanpostprocessor();
 }

 /**
  * 注入 密码登录customrealm
  */
 @bean
 @dependson("lifecyclebeanpostprocessor")
 public userpasswordrealm userpasswordrealm() {
  return new userpasswordrealm();
 }

 /**
  * 注入 邮箱验证登录emailrealm
  */
 @bean
 @dependson("lifecyclebeanpostprocessor")
 public useremailrealm useremailrealm() {
  return new useremailrealm();
 }

 /**
  * 默认安全管理器
  */
 @bean
 public defaultwebsecuritymanager securitymanager(userpasswordrealm userpasswordrealm, useremailrealm useremailrealm, abstractauthenticator abstractauthenticator) {
  defaultwebsecuritymanager defaultwebsecuritymanager = new defaultwebsecuritymanager();
  list<realm> realms = new arraylist<>();
  realms.add(userpasswordrealm);
  realms.add(useremailrealm);
  defaultwebsecuritymanager.setrealms(realms);
  // 记住我
  defaultwebsecuritymanager.setremembermemanager(cookieremembermemanager());
  defaultwebsecuritymanager.setauthenticator(abstractauthenticator);
  return defaultwebsecuritymanager;
 }

 /**
  * 认证器 把我们的自定义验证加入到认证器中
  */
 @bean
 public abstractauthenticator abstractauthenticator(userpasswordrealm userpasswordrealm, useremailrealm useremailrealm) {
  // 自定义模块化认证器,用于解决多realm抛出异常问题
  //开始没用自定义异常问题,发现不管是账号密码错误还是什么错误
  //shiro只会抛出一个authenticationexception异常
  modularrealmauthenticator authenticator = new mycustommodularrealmauthenticator();
  // 认证策略:atleastonesuccessfulstrategy(默认),allsuccessfulstrategy,firstsuccessfulstrategy
  authenticator.setauthenticationstrategy(new atleastonesuccessfulstrategy());
  // 加入realms
  list<realm> realms = new arraylist<>();
  realms.add(userpasswordrealm);
  realms.add(useremailrealm);
  authenticator.setrealms(realms);
  return authenticator;
 }

 /**
  * 加入shiro注解 代理生成器 切面
  */
 @bean
 @dependson({"lifecyclebeanpostprocessor"})
 public defaultadvisorautoproxycreator advisorautoproxycreator() {
  defaultadvisorautoproxycreator advisorautoproxycreator = new defaultadvisorautoproxycreator();
  advisorautoproxycreator.setproxytargetclass(true);
  return advisorautoproxycreator;
 }

 /**
  * 加入shiro注解 切点
  */
 @bean
 public authorizationattributesourceadvisor authorizationattributesourceadvisor(defaultwebsecuritymanager securitymanager) {
  authorizationattributesourceadvisor authorizationattributesourceadvisor = new authorizationattributesourceadvisor();
  authorizationattributesourceadvisor.setsecuritymanager(securitymanager);
  return authorizationattributesourceadvisor;
 }

 /**
  * 设置cookie 记住我生成cookie
  */
 @bean
 public cookieremembermemanager cookieremembermemanager() {
  cookieremembermemanager cookieremembermemanager = new cookieremembermemanager();
  cookieremembermemanager.setcookie(remembermecookie());
  return cookieremembermemanager;
 }

 /**
  * 设置cookie有效时间
  */
 @bean
 public simplecookie remembermecookie() {
  /*这个参数是cookie的名称,对应前端页面的checkbox的name=remremberme*/
  simplecookie simplecookie = new simplecookie("rememberme");
  /*cookie的有效时间为30天,单位秒*/
  simplecookie.setmaxage(259200);
  return simplecookie;
 }

}

创建自定义验证器 mycustommodularrealmauthenticator 类

public class mycustommodularrealmauthenticator extends modularrealmauthenticator {

 @override
 protected authenticationinfo domultirealmauthentication(collection<realm> realms, authenticationtoken token) {
  authenticationstrategy authenticationstrategy = this.getauthenticationstrategy();
  authenticationinfo authenticationinfo = authenticationstrategy.beforeallattempts(realms, token);

  iterator var5 = realms.iterator();
  while (var5.hasnext()) {
   realm realm = (realm) var5.next();
   authenticationinfo = authenticationstrategy.beforeattempt(realm, token, authenticationinfo);
   if (realm.supports(token)) {

    authenticationinfo info = null;
    throwable t = null;

    info = realm.getauthenticationinfo(token);

    authenticationinfo = authenticationstrategy.afterattempt(realm, token, info, authenticationinfo, t);
   }
  }
  authenticationinfo = authenticationstrategy.afterallattempts(token, authenticationinfo);
  return authenticationinfo;
 }
}

创建密码登录时验证授权 userpasswordrealm 类

@component
public class userpasswordrealm extends authorizingrealm {

 // 注入用户业务
 @autowired
 private usermapper usermapper;

 /**
  * 授权
  */
 @override
 protected authorizationinfo dogetauthorizationinfo(principalcollection principals) {
  system.out.println("————密码授权————dogetauthorizationinfo————");

  return null;
 }

 /**
  * 认证
  */
 @override
 protected authenticationinfo dogetauthenticationinfo(authenticationtoken token) throws authenticationexception {
  system.out.println("————密码认证————dogetauthenticationinfo————");

  usernamepasswordtoken usertoken = (usernamepasswordtoken) token;
  // 连接数据库 查询用户数据
  querywrapper<user> wrapper = new querywrapper<>();
  wrapper.eq("user_name", usertoken.getusername());
  user user = usermapper.selectone(wrapper);
  // 验证用户
  if (user == null) {
   throw new unknownaccountexception();
  }
  return new simpleauthenticationinfo("", user.getuserpassword(), "");
 }

 /**
  * 用来判断是否使用当前的 realm
  *
  * @param var1 传入的token
  * @return true就使用,false就不使用
  */
 @override
 public boolean supports(authenticationtoken var1) {
  return var1 instanceof usernamepasswordtoken;
 }

}

创建邮件验证码登录时验证授权useremailrealm

@component
public class useremailrealm extends authorizingrealm {

 // 注入用户业务
 @autowired
 userservice userservice;

 @override
 protected authorizationinfo dogetauthorizationinfo(principalcollection principalcollection) {
  system.out.println("————邮箱登录授权————dogetauthorizationinfo————");
  return null;
 }

 @override
 protected authenticationinfo dogetauthenticationinfo(authenticationtoken token) throws authenticationexception {
  system.out.println("————邮箱登录认证————dogetauthenticationinfo————");
  useremailtoken useremailtoken = (useremailtoken) token;
  string useremail = (string) useremailtoken.getprincipal();
  // 连接数据库 查询用户数据
  querywrapper<user> wrapper = new querywrapper<>();
  wrapper.eq("user_email", useremail);
  user user = userservice.getone(wrapper);
  //因为没有密码,并且验证码在之前就验证了
  if (user == null) {
   throw new unknownaccountexception();
  }
  return new simpleauthenticationinfo("", useremail, "");
 }

 /**
  * 用来判断是否使用当前的 realm
  *
  * @param var1 传入的token
  * @return true就使用,false就不使用
  */
 @override
 public boolean supports(authenticationtoken var1) {
  return var1 instanceof useremailtoken;
 }
}

创建邮件验证码登录验证通过生成令牌的 useremailtoken 类(密码登录时使用shiro默认的 usernamepasswordtoken 令牌)

@data // 使用lombok 生成get方法、set方法
public class useremailtoken implements hostauthenticationtoken, remembermeauthenticationtoken {

 private string useremail;
 private boolean rememberme;
 private string host;

 public useremailtoken() {
  this.rememberme = false;
 }

 public useremailtoken(string useremail) {
  this(useremail, false, null);
 }

 public useremailtoken(string useremail, boolean rememberme) {
  this(useremail, rememberme, null);
 }

 public useremailtoken(string useremail, boolean rememberme, string host) {
  this.useremail = useremail;
  this.rememberme = rememberme;
  this.host = host;
 }

 @override
 public string gethost() {
  return host;
 }

 @override
 public boolean isrememberme() {
  return rememberme;
 }

 /**
  * 重写getprincipal方法
  */
 @override
 public object getprincipal() {
  return useremail;
 }

 /**
  * 重写getcredentials方法
  */
 @override
 public object getcredentials() {
  return useremail;
 }
}

创建密码盐值加密 mdpasswordutil 工具类

public class mdpasswordutil {

 public string getmdpasswordutil(string username, string userpassword) {
  string hashalgorithmname = "md5"; // 加密方式:md5加密
  object credentials = userpassword; // 密码
  object salt = bytesource.util.bytes(username); // 盐
  int hashiterations = 512; // 加密次数
  object result = new simplehash(hashalgorithmname, credentials, salt, hashiterations);
  return result.tostring();
 }
}

控制层用户密码登录

// 用户密码登录
 @postmapping("/passwordlogin")
 public string userlogin(@requestparam("username") string username,
       @requestparam("userpassword") string userpassword,
       httpsession session, model model) {
  // 获取当前的用户
  subject subject = securityutils.getsubject();
  // 对密码进行md5盐值加密
  string md5password = new mdpasswordutil().getmdpasswordutil(username, userpassword);
  // 封装用户的登录数据
  usernamepasswordtoken token = new usernamepasswordtoken(username, md5password);
  //rememberme记住我
  token.setrememberme(true);
  try {
   // 登录,验证,保存令牌
   subject.login(token);

   //查询登录信息
   querywrapper<user> wrapper = new querywrapper<>();
   wrapper.eq("user_name", username);
   user user = userservice.getone(wrapper);
   //保存登录用户信息
   session.setattribute(user.getuserid().tostring(), user);

   return "admin";
  } catch (unknownaccountexception e) {
   model.addattribute("usererror", "用户名错误!请重新输入。");
   return "login";
  } catch (incorrectcredentialsexception ice) {
   model.addattribute("pwerror", "密码错误!请重新输入。");
   return "login";
  }
 }

控制层用户邮件验证码密码登录

// 用户邮箱登录
 @postmapping("/emaillogin")
 public string emaillogin(@requestparam("useremail") string useremail,
        @requestparam("emailcode") string emailcode,
        httpsession session, model model) {
  // 根据useremail从session中取出发送的验证码
  string sendemailcode = (string) session.getattribute(useremail);
  // 比对验证码
  if (stringutils.isnoneblank(sendemailcode) && sendemailcode.equals(emailcode)) {
   try {
    useremailtoken token = new useremailtoken(useremail);
    //rememberme记住我
    token.setrememberme(true);
    // 登录,验证,保存令牌
    subject subject = securityutils.getsubject();
    subject.login(token);

    //查询登录信息
    querywrapper<user> wrapper = new querywrapper<>();
    wrapper.eq("user_email", useremail);
    user user = userservice.getone(wrapper);
    //保存登录用户信息
    session.setattribute(user.getuserid().tostring(), user);

    // 销毁验证码
    session.removeattribute(emailcode);

    return "admin";
   } catch (exception e) {
    model.addattribute("error", "验证码错误!请重新输入。");
    return "login";
   }
  } else {
   return "login";
  }
 }

springboot 整合 shiro 密码登录与邮件验证码登录(多 realm 认证)就可以了 (有点多,哈哈哈)

推荐大神:狂神说java

到此这篇关于springboot 整合 shiro 密码登录与邮件验证码登录(多 realm 认证)的文章就介绍到这了,更多相关springboot 整合 shiro登录内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!