Shiro整合springboot项目实战(前端是使用jsp实现)---登录功能

代码实现

login.jsp

<%@page contentType="text/html; UTF-8" pageEncoding="utf-8" isELIgnored="false" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</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" %>
<%--引用shiro的标签--%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>系统用户</h1>
<%--拿到用户名的标签--%>
<h1><shiro:principal/></h1>
<shiro:authenticated>
    认证之后才能展示的内容,如果没有认证就不会展示,可以用于公共页面。
</shiro:authenticated>
<shiro:notAuthenticated>
    没有认证之后的展示内容
</shiro:notAuthenticated>
<ul>
<%--    设置多个用户--%>
    <shiro:hasAnyRoles name="admin,user">
        <li><a href="href">用户管理</a>
            <ul>
                <shiro:hasPermission name="user:add:*">
                <li><a href="">添加</a></li>
                </shiro:hasPermission>
                <shiro:hasPermission name="user:delete:*">
                <li><a href="">删除</a></li>
                </shiro:hasPermission>
                <shiro:hasPermission name="user:update:*">
                <li><a href="">修改</a></li>
                </shiro:hasPermission>
                <shiro:hasPermission name="order:find:*">
                <li><a href="">查询</a></li>
                </shiro:hasPermission>

            </ul>
        </li>
    </shiro:hasAnyRoles>
    <%--    shiro标签的功能,在这个标签里面的链接能被admian使用,其他角色是看不见的--%>
    <shiro:hasRole name="admin">
        <li><a href="href">商品管理</a></li>
    </shiro:hasRole>
    <a href="${pageContext.request.contextPath}/user/logout">退出登录</a>
</ul>
</body>
</html>

userController:


    /**
     * 用来处理身份认证
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("login")
    public String login(String username,String password,String code,HttpSession session){
//        比较验证码
        String codes = (String) session.getAttribute("code");
        try {
            if (codes.equalsIgnoreCase(code)) {
//        获取主体对象,和Java项目相比,是不用另外去创建安全管理器的,因为我们在shiro的配置类中声明了安全管理器。
                Subject subject = SecurityUtils.getSubject();
                subject.login(new UsernamePasswordToken(username, password));
                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();
            System.out.println(e.getMessage());
        }
        return "redirect:/login.jsp";
    }

customerRealm:

package shiro.demo.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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.CollectionUtils;
import shiro.demo.Untils.ApplicationContextUtils;
import shiro.demo.Untils.MyByteSource;
import shiro.demo.entity.Pers;
import shiro.demo.entity.Role;
import shiro.demo.entity.User;
import shiro.demo.service.UserService;

import java.util.List;

//自定义realm
public class CustomerRealm extends AuthorizingRealm {


    @Override
//    realm授权,用这个方法去获取权限信息
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        获取身份信息
        String  primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
//        根据主身份信息获取角色和权限信息(测试数据)
//        if("xiaochen".equals(primaryPrincipal)){
//            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//            /**
//             * //给这个对象添加普通用户的角色,但是问题是,就算是添加了用户角色,
//             * 但是系统并不知道普通用户具有什么样的权限,获取超级管理员又有什么权限,
//             * 所以要在前端页面进行加上一些标签进行权限控制,就规定普通用户能看到那些东西
//             */
//            simpleAuthorizationInfo.addRole("user");
//            simpleAuthorizationInfo.addStringPermission("user:update:*");
//            simpleAuthorizationInfo.addStringPermission("user:select:*");
//            return simpleAuthorizationInfo;
//        }
        UserService userServiceImpl = (UserService) ApplicationContextUtils.getBean("userServiceImpl");
        User user = userServiceImpl.findRolesByUserName(primaryPrincipal);
//        授权角色信息
        if (!CollectionUtils.isEmpty(user.getRoles())){
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            for (Role role : user.getRoles()) {
                System.out.println(role.getRoleId());
//                角色信息
                simpleAuthorizationInfo.addRole(role.getRoleName());
//                权限信息
                List<Pers> pers = userServiceImpl.findPersByRoleId(role.getRoleId());
                System.out.println(pers);
                if (!CollectionUtils.isEmpty(pers)){
                    for (Pers per : pers) {
                        simpleAuthorizationInfo.addStringPermission(per.getName());
                    }
                }


            }
            return simpleAuthorizationInfo;
        }
//        连接数据库进行授权的代码块
//      通过工厂去拿业务对象

        return null;
    }
//realm认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        获取身份信息
        String principal = (String) authenticationToken.getPrincipal();
//        在工厂中获取service对象,并且强转类型,获取后台返回的user对象
        UserService userServiceImpl = (UserService) ApplicationContextUtils.getBean("userServiceImpl");
        User user = userServiceImpl.findByUserName(principal);
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, "123", this.getName());
        if(user!=null){
            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), new MyByteSource(user.getSalt()),this.getName());
        }
        return null;
    }
}

ApplicationContextUtils:这个类的主要目的是,我们在serviceimpl中获取到返回的user对象,但是我们的realm拿不到这个对象,因为realm没有在工厂中, 没有办法获取注入的值,所以这个工具类的作用就是,帮助realm获取工厂注入的对象

package shiro.demo.Untils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 这个类的主要目的是,我们在serviceimpl中获取到返回的user对象,但是我们的realm拿不到这个对象,因为realm没有在工厂种
 * 没有办法获取注入的值,所以这个工具类的作用就是,帮助realm获取工厂注入的对象。
 */
@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context=applicationContext;

    }

//    根据bean的名字来获取指定的bean对象
    public static Object getBean(String beanName){
        Object bean = context.getBean(beanName);
        return bean;
    }
}

userServiceImpl:
三个方法,
一个是根据用户名去对比数据库中的数据看是否可以登录成功。
一个是根据用户名去获取这个用户的角色
另一个是根据角色名去获取权限

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

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

userDao:

  User findByUserName(String username);

    User findRolesByUserName(String username);

//    根据角色的id查询权限集合
    List<Pers> findPersByRoleId(Integer roleId);

userDao.xml:

 <select id="findByUserName" resultType="shiro.demo.entity.User">
        select id,username,password,salt from t_user
        where username=#{username}

    </select>
    <resultMap id="userMap" type="User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
<!--                角色信息-->
        <collection property="roles" javaType="list" ofType="Role">
            <id column="role_id" property="roleId"/>
            <result column="role_name" property="roleName"/>
        </collection>
    </resultMap>
    <select id="findRolesByUserName" parameterType="String" resultMap="userMap">
        select u.id,u.username,r.role_id,r.role_name from t_user u
                                              LEFT JOIN t_user_role ur on u.id=ur.user_id
                                              LEFT JOIN t_role r on ur.role_id=r.role_id
        where u.username=#{username}
    </select>
    <select id="findPersByRoleId" resultType="shiro.demo.entity.Pers">
        select p.* from t_role r
        LEFT JOIN t_role_pers rp
        ON r.role_id=rp.role_id
        LEFT JOIN t_pers p
        ON p.id=rp.pers_id
        where r.role_id=#{roleId}
    </select>

shiroConfig:
在config中设置紫铜的受限资源和公共资源

package shiro.demo.config;



import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
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 shiro.demo.Cache.RedisCacheManager;
import shiro.demo.realms.CustomerRealm;

import java.util.HashMap;
import java.util.Map;

//这是用来整合shiro框架相关的配置类
@Configuration
public class shiroConfig {
//    1,创建shiroFilter,负责拦截所有请求的
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//        给filter设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

//        配置系统的受限资源
//        配置系统的公共资源
        Map<String, String> map = new HashMap<>();
        map.put("/user/register","anon");//设置注册方式为公共资源
        map.put("/register.jsp","anon");//设置注册页面为公共资源
        map.put("/user/login","anon");  //anon 就是不用认证和授权,是公共的资源
        map.put("/user/getImg","anon");
        map.put("/**","authc");//authc 请求这个资源需要认证和授权,除了上面的login.jsp资源不受限,其他的资源都是受限的。
        System.out.println(map);
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        //默认认证的界面路径,这个地方不写默认的就是login.jsp页面,但是也可以改成别的。
//        shiroFilterFactoryBean.setLoginUrl("/login.jsp");
    return shiroFilterFactoryBean;
    }
//    2,创建安全管理器
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("getRealm") Realm realm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//        给安全管理器设置realm
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }

//    3,创建自定义realm
    @Bean
    public Realm getRealm(){
        CustomerRealm customerRealm = new CustomerRealm();
//      因为这里我们使用MD5+salt+hash的密码进行匹配的,所以我们要更改一下默认的密码匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//        设置加密算法为MD5
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
//        设置散列次数
        hashedCredentialsMatcher.setHashIterations(1024);
        customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值