shiro + springboot记住密码(java配置版)

前端页面

<div style="margin-left:auto; margin-right:auto;width:200px;height:100px;">
    <form th:action="@{/login}">
        <h1 style="text-align:center">登录</h1><br/>
        <p style="color:red;" th:text="${msg}"></p>
        用户名:<input type="text" name="username"><br/>
        密码: <input type="password" name="password"><br/>
        <input type="checkbox" name="rememberMe"><span>记住密码</span>
        <br/>
        <input type="submit" value="登录"><br/>
    </form>
</div>

实体类User.java(实体类需要序列化)

import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable{

    private static final long serialVersionUID = 69667703L;

    private String userName;
    private String password;
    private String perms;
}

ShiroConfig.java

package com.loey.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
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
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

         //设置安全管理器    
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String, String> filterMap = new LinkedHashMap<String,String>();

         /*  
                添加Shiro内置过滤器,常用的有如下过滤器:          
                anon: 无需认证就可以访问            
                authc: 必须认证才可以访问  
                user: 如果使用了记住我功能就可以直接访问   
                perms:  拥有某个资源权限才可以访问
                role: 拥有某个角色权限才可以访问     
          */
//        filterMap.put("/user/add","authc");
//        filterMap.put("/user/update","authc");

        //授权过滤器
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");

        filterMap.put("/user/*","user");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");


        //修改要跳转的login页面
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        return shiroFilterFactoryBean;
    }


     //创建 DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm,@Qualifier("cookieRememberMeManager") CookieRememberMeManager cookieRememberMeManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //关联Realm
        securityManager.setRealm(userRealm);

        securityManager.setRememberMeManager(cookieRememberMeManager);
        return securityManager;
    }

    @Bean(name = "cookie")
    public SimpleCookie getCookie(){

        SimpleCookie cookie = new SimpleCookie("rememberMe");

        cookie.setHttpOnly(true);
        cookie.setMaxAge(604800);
        return cookie;
    }

    @Bean("cookieRememberMeManager")
    public CookieRememberMeManager getCookieRememberMeManager(@Qualifier("cookie") SimpleCookie cookie){

        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();

        cookieRememberMeManager.setCookie(cookie);
         // rememberMe cookie加密的密钥     
          cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));

        return cookieRememberMeManager;
    }

     //创建 realm 对象
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //配置ShiroDialect:方言,用于 thymeleaf 和 shiro 标签配合使用
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

UserRealm.java

package com.loey.config;

import com.loey.pojo.User;
import com.loey.service.UserService;
import org.apache.catalina.security.SecurityUtil;
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;

//自定义Realm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    //执行授权逻辑
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了=>授权逻辑PrincipalCollection");

        //给资源授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //添加资源的授权字符串
       /* info.addStringPermission("user:add");
        info.addStringPermission("user:update");*/

        //获得当前对象
        Subject subject = SecurityUtils.getSubject();
        //拿到user对象
        User currentUser = (User) subject.getPrincipal();

        //设置权限
        info.addStringPermission(currentUser.getPerms());

        return info;
    }

    //执行认证逻辑
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=>认证逻辑AuthenticationToken");

        //1.判断用户名
      UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        //真实连接数据库
        User user = userService.queryUserByName(userToken.getUsername());
        if(user == null){
            //用户名不存在
            return null;//shiro底层会抛出 UnknownAccountException
        }

        Subject subject = SecurityUtils.getSubject();
        subject.getSession().setAttribute("loginUser",user);

        //2. 验证密码,我们可以使用一个AuthenticationInfo实现类 SimpleAuthenticationInfo    
        //   shiro会自动帮我们验证!重点是第二个参数就是要验证的密码
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
}

UserMapper.java

package com.loey.mapper;

import com.loey.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {

    public User queryUserByName(@Param("userName") String userName);
}

UserMapper.xml

<?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">
<!--namespace=绑定一个对应的mapper/Mapper接口-->
<mapper namespace="com.loey.mapper.UserMapper">

    <select id="queryUserByName" resultType="User">
        select * from user where username = #{userName};
    </select>


</mapper>

MyController.java

    //登录操作
    @RequestMapping("/login")
    public String login(String username,String password,String rememberMe,Model model){

        //使用shiro编写认证操作

        //1.获取Subject(当前用户)
        Subject subject = SecurityUtils.getSubject();

        //2.封装用户的数据
               UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        if("on".equals(rememberMe)){
            token.setRememberMe(true);//调用Shiro记住我API方法
        }else{
            token.setRememberMe(false);
        }
        //3.执行登录的方法,只要没有异常就代表登录成功
        try {
            subject.login(token);
            return "index";
        }catch (UnknownAccountException uae) {//如果没有指定的用户,则 UnknownAccountException异常
            model.addAttribute("msg","用户名不存在");
            return "login";
        } catch (IncorrectCredentialsException ice) {//密码不对的异常
            model.addAttribute("msg","密码错误");
            return "login";
        }

    }

页面视图

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值