关于学习Shiro的一些笔记总结(二)

获取源码和笔记地址:https://gitee.com/monologue_zsj/shiro.git (上篇文章地址:https://blog.csdn.net/weixin_42047611/article/details/114519074)


2、shiro-SpringBoot-jsp

server.port=8888
server.servlet.context-path=/shiro
spring.application.name=shiro

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/siasr?characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456

mybatis.type-aliases-package=com.monologue.entity
mybatis.mapper-locations=classpath:mapper/*.xml

logging.level.com.monologue.mapper=debug
<!--JSP 的依赖-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

<!--引入SpringBoot整合Shiro依赖-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>1.5.3</version>
</dependency>
<%--resource/webapp/index.jsp(login.jsp,register.jsp):账户密码提交--%>
<%@ page language="java" contentType="text/html; charset=utf-8"
         pageEncoding="utf-8"%>

<%@taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Index</title>
</head>
<body>
    <h1>系统主页 v1.0</h1>
    
    <%--主身份信息--%>
    <h1><shiro:principal/></h1>
    <shiro:authenticated>
        认证之后展示的信息
    </shiro:authenticated>

    <shiro:notAuthenticated>
        没有认证之后展示的信息
    </shiro:notAuthenticated>
    
    <a href="${pageContext.request.contextPath}/user/logout">退出登录</a>
    <ul>
        <shiro:hasAnyRoles name="user,admin">
            <li><a href="">用户管理</a>
                <ul>
                    <shiro:hasPermission name="user:add:*">
                        <li><a href="">insert</a></li>
                    </shiro:hasPermission>
                    <shiro:hasPermission name="user:delete:*">
                        <li><a href="">delete</a></li>
                    </shiro:hasPermission>
                    <shiro:hasPermission name="user:update:*">
                        <li><a href="">update</a></li>
                    </shiro:hasPermission>
                    <shiro:hasPermission name="user:find:*">
                        <li><a href="">select</a></li>
                    </shiro:hasPermission>
                </ul>
            </li>
        </shiro:hasAnyRoles>
        <shiro:hasRole name="admin">
            <li><a href="">商品管理</a></li>
            <li><a href="">订单管理</a></li>
            <li><a href="">物流管理</a></li>
            <li><a href="">系统管理</a></li>
        </shiro:hasRole>
    </ul>
</body>
</html>
/**
 * Created by Monologue_zsj on 2021/3/7 14:38
 * Author:小脸儿红扑扑
 * Description:整合Shiro框架相关的配置类
 */
@Configuration
public class ShiroConfig {

    //1、创建ShiroFilter (负责拦截所有请求)
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //给Filter设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //配置系统受限资源和系统公共资源
        Map<String, String> map = new HashMap<>();
        map.put("/user/login", "anon");  //anon 指定url可以匿名访问
        map.put("/user/register", "anon");  //anon 指定url可以匿名访问
        map.put("/register.jsp", "anon");  //anon 指定url可以匿名访问
        map.put("/**", "authc");     //authc 请求这个资源需要认证和授权
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        //默认认证界面路径
        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();
        //修改凭证校验匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //设置加密算法为md5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //设置散列次数
        credentialsMatcher.setHashIterations(1024);
        customerRealm.setCredentialsMatcher(credentialsMatcher);
        return customerRealm;
    }
}

//service
@Override
public void register(User user) {

    //明文密码进行MD5 + salt + hash散列
    //1、生成随机盐
    String salt = SaltUtils.getSalt(8);
    //2、将随机盐保存的数据库
    user.setSalt(salt);

    Md5Hash md5Hash = new Md5Hash(user.getPassword(), salt, 1024);
    user.setPassword(md5Hash.toHex());

    userMapper.save(user);
}
/**
 * Created by Monologue_zsj on 2021/3/7 16:19
 * Author:小脸儿红扑扑
 * Description:根据beanName获取工厂中指定的bean对象
 */
@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

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

    public static Object getBean(String beanName) {
        return context.getBean(beanName);
    }
}
/**
 * Created by Monologue_zsj on 2021/3/7 14:52
 * Author:小脸儿红扑扑
 * Description:自定义Realm
 */
public class CustomerRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {

        //获取身份信息
        String primaryPrincipal = (String) principal.getPrimaryPrincipal();

        //根据主身份信息获取角色和权限信息(模拟数据)
        if ("zsj".equals(primaryPrincipal)) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            simpleAuthorizationInfo.addRole("user");

            simpleAuthorizationInfo.addStringPermission("user:find:*");

            return simpleAuthorizationInfo;
        }

        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        System.out.println("_________________________");
        String principal = (String) token.getPrincipal();

        //在工厂中获取service对象
        UserService userService = (UserService) ApplicationContextUtils.getBean("userServiceImpl");

        User user = userService.findByUserName(principal);

        if (!ObjectUtils.isEmpty(user)) {
            return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), this.getName());
        }
        return null;
    }
}

常见过滤器

配置缩写对应的过滤器功能
anonAnonymousFilter指定url可以匿名访问
authcFormAuthenticationFilter指定url需要form表单登录,默认会从请求中获取username,password,rememberMe 等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回的信息都可以定制嘛。
authcBasicBasicHttpAuthenticationFilter指定url需要basic登录
logoutLogoutFilter登出过滤器,配置指定url就可以实现退出功能,非常方便
noSessionCreationNoSessionCreationFilter禁止创建会话
permsPermissionsAuthorizationFilter需要指定权限才能访问
portPortFilter需要指定端口才能访问
restHttpMethodPermissionFilter将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大,有兴趣自己看源码的注释
rolesRolesAuthorizationFilter需要指定角色才能访问
sslSslFilter需要ssl请求才能访问
userUserFilter需要已登录或“记住我”的用户才能访问
/**
 * Created by Monologue_zsj on 2021/3/7 14:52
 * Author:小脸儿红扑扑
 * Description:自定义Realm
 */
public class CustomerRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {

        //获取身份信息
        String primaryPrincipal = (String) principal.getPrimaryPrincipal();
        //根据主身份信息获取角色 和 权限信息
        UserService userService = (UserService) ApplicationContextUtils.getBean("userServiceImpl");
        User user = userService.findRolesByUsername(primaryPrincipal);

        //根据主身份信息获取角色和权限信息
        if (!CollectionUtils.isEmpty(user.getRoles())) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            user.getRoles().forEach(role -> {
                simpleAuthorizationInfo.addRole(role.getName());
                //权限信息
                List<Permission> permissions = userService.findPermissionByRoleId(role.getId());
                if (!CollectionUtils.isEmpty(permissions)) {
                    permissions.forEach(permission -> {
                        simpleAuthorizationInfo.addStringPermission(permission.getName());
                    });
                }
            });
            return simpleAuthorizationInfo;
        }

        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        System.out.println("_________________________");
        String principal = (String) token.getPrincipal();

        //在工厂中获取service对象
        UserService userService = (UserService) ApplicationContextUtils.getBean("userServiceImpl");

        User user = userService.findByUserName(principal);

        if (!ObjectUtils.isEmpty(user)) {
            return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), this.getName());
        }
        return null;
    }
}
/**
 * Created by Monologue_zsj on 2021/3/7 15:22
 * Author:小脸儿红扑扑
 * Description:
 */
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/register")
    public String register(User user) {

        try {
            userService.register(user);
            return "redirect:/login.jsp";
        } catch (Exception e) {
            e.printStackTrace();
            return "redirect:/register.jsp";
        }
    }

    @RequestMapping("/login")
    public String login(String username, String password) {

        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        try {
            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("密码错误...");
        }
        return "redirect:/login.jsp";
    }

    @RequestMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "redirect:/login.jsp";
    }
}
/**
 * Created by Monologue_zsj on 2021/3/7 17:01
 * Author:小脸儿红扑扑
 * Description:
 */
@Controller
@RequestMapping("/order")
public class OrderController {

    @RequestMapping("/save")
    //@RequiresRoles("admin")   //需要那个角色
    //@RequiresPermissions("user:*:*")    //用来判断权限字符串
    public String save() {
        //获取主体对象
        //Subject subject = SecurityUtils.getSubject();
        //代码方式
        /*if (subject.hasRole("admin")) {
            System.out.println("保存订单");
        }else {
            System.out.println("权限不足");
        }

        if (subject.isPermitted("user:*:*")) {
            System.out.println("保存订单");
        }else {
            System.out.println("权限不足");
        }*/

        return "redirect:/index.jsp";
    }
}
int save(User user);

@Select("select * from shiro_user where username = #{username}")
User findByUserName(String username);

//根据用户名查询角色
User findRolesByUsername(String username);

//根据角色id查询权限集合
List<Permission> findPermissionByRoleId(Integer id);
        
<?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.monologue.mapper.UserMapper">
    <insert id="save" parameterType="User" keyProperty="id" useGeneratedKeys="true">
        insert into shiro_user values (#{id}, #{username}, #{password}, #{salt})
    </insert>

    <resultMap id="UserMap" type="User">
        <id column="uid" property="id" />
        <result column="username" property="username" />
        <!--角色信息-->
        <collection property="roles" javaType="java.util.List" ofType="Role">
            <id column="id" property="id" />
            <result column="rname" property="name" />
        </collection>
    </resultMap>

    <select id="findRolesByUsername" parameterType="String" resultMap="UserMap">
        select u.id uid, u.username, r.id, r.name rname
        from shiro_user u
        left join t_user_role ur
        on u.id = ur.userid
        left join s_role r
        on ur.roleid = r.id
        where u.username = #{username}
    </select>

    <select id="findPermissionByRoleId" parameterType="Integer" resultType="Permission">
        select p.id, p.name, p.url, r.name
        from s_role r
        left join t_role_permission rp
        on r.id = rp.roleid
        left join s_permission p
        on rp.permissionid = p.id
        where r.id = #{id}
    </select>
</mapper>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值