spring boot + jsp +shiro最简demo

因工作需要 项目开发新需求,需要加入权限,权限细化到每个按钮,实在是坑…以前怎么没用过shiro,本想着直接从session中拿user后台注入权限 不去登录,页面直接用标签控制权限。结果页面拿不到权限。猜测是权限匹配不到用户,还是做了登录。
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)方法里处理一下就OK了,
现登录模块是其他项目组(session共享) ,后续尝试从拦截器去做shiro登录验证;

1、pom.xml

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<!-- JSP begin -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<!-- JSP end -->
        <!-- shiro -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-all</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>

2、项目配置文件 application.properties

server.port=9900

# 页面默认前缀目录
spring.mvc.view.prefix=/WEB-INF/jsp/
# 响应页面默认后缀
spring.mvc.view.suffix=.jsp
spring.mvc.date-format=yyyy-MM-dd
spring.jackson.date-format=yyyy-MM-dd
spring.jackson.time-zone=GMT+8

3、springboot 启动类 ShiroApplication

package vip.sweet.smile.shiro;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ShiroApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class, args);
    }

}

4 、shiro 认证 ShiroRealm

package vip.sweet.smile.shiro.auth;

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.springframework.stereotype.Component;
import vip.sweet.smile.shiro.pojo.Menu;
import vip.sweet.smile.shiro.pojo.Role;
import vip.sweet.smile.shiro.pojo.User;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Component
public class ShiroRealm extends AuthorizingRealm {


    @Override
    public String getName() {
        return "shiroRealm";
    }

    /**
     * 获取用户权限
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //从shiro中获取user对象
        User user = (User) SecurityUtils.getSubject().getPrincipal();

        // 根据 user对象从数据库中获取用户角色、权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //此处 简化查询角色信息(非本文重点) 直接构造角色
        // 获取用户角色集
        List<Role >roleList = new ArrayList<>();
        Role role = new Role();
        role.setRoleName("admin");
        roleList.add(role);
        Set<String> roleSet = roleList.stream().map(Role::getRoleName).collect(Collectors.toSet());
        //设置用户角色  Set<String>
        simpleAuthorizationInfo.setRoles(roleSet);

        // 获取用户权限集
        List<Menu> permissionList = new ArrayList<>();
        Menu update = new Menu();
        update.setMenuId(1L);
        update.setPerms("dept:update");
        permissionList.add(update);

        Menu add = new Menu();
        add.setMenuId(2L);
        add.setPerms("dept:add");
        permissionList.add(add);
        Set<String> permissionSet = permissionList.stream().map(Menu::getPerms).collect(Collectors.toSet());
        //设置用户权限  Set<String>
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

	/**
     * 登录验证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //token中获取用户名密码
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        //从数据库 根据用户名查询 用户信息(非重点略)
        User user = new User();
        user.setUsername(username);
        user.setId(1);
		// 这边如果验证不通过 则可以抛出异常 在登录接口可以捕获
		/*if(user == null){
			throw new AuthenticationException(“NO_USER”);
		}*/
		//创建 SimpleAuthenticationInfo会将用户信息放入shiro维护的用户集合
        return new SimpleAuthenticationInfo(user, password, getName());
    }
}

附 SimpleAuthenticationInfo 相关源码片段

public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName) {
    this.principals = new SimplePrincipalCollection(principal, realmName);
    this.credentials = credentials;
}
public SimplePrincipalCollection(Object principal, String realmName) {
    if (principal instanceof Collection) {
        this.addAll((Collection)principal, realmName);
    } else {
        this.add(principal, realmName);
    }

}
public void addAll(Collection principals, String realmName) {
   if (realmName == null) {
       throw new IllegalArgumentException("realmName argument cannot be null.");
   } else if (principals == null) {
       throw new IllegalArgumentException("principals argument cannot be null.");
   } else if (principals.isEmpty()) {
       throw new IllegalArgumentException("principals argument cannot be an empty collection.");
   } else {
       this.cachedToString = null;
       this.getPrincipalsLazy(realmName).addAll(principals);
   }
}

5、shiro配置文件 ShiroConfig

package vip.sweet.smile.shiro.config;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import vip.sweet.smile.shiro.auth.ShiroRealm;

import java.util.LinkedHashMap;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 设置 securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 登录的URL
        //shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后跳转的UR
        //shiroFilterFactoryBean.setSuccessUrl("/index");
        // 未授权URL
       // shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 设置免认证 url
        filterChainDefinitionMap.put("/index", "anon");

        // 配置退出过滤器,其中具体的退出代码 Shiro已经替我们实现了
        filterChainDefinitionMap.put("/login", "logout");

        // 除上以外所有 url都必须认证通过才可以访问,未通过认证自动访问 LoginUrl
        filterChainDefinitionMap.put("/**", "user");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager(ShiroRealm shiroRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 配置 SecurityManager,并注入 shiroRealm
        securityManager.setRealm(shiroRealm);
        // 配置 shiro session管理器
        //securityManager.setSessionManager(sessionManager());
        // 配置 缓存管理类 cacheManager
       // securityManager.setCacheManager(cacheManager());
        // 配置 rememberMeCookie
        //securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

}

6、登录Controller IndexAction

package vip.sweet.smile.shiro.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
public class IndexAction {

    @RequestMapping(value = "index")
    public String toIndex(HttpServletRequest request){
		//简化处理 没有任何判断 直接跳转 index页
		//从前端获取用户名密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        UsernamePasswordToken upt = new UsernamePasswordToken(username,password);
       	//用户名 密码 token 调用 subject.login 方法登录将用户信息注入shiro 
       	//会去调用ShiroRealm.doGetAuthenticationInfo(AuthenticationToken token) 验证用户信息
        Subject subject = SecurityUtils.getSubject();
        try{
        	subject.login(upt);
        }catch(Exception e){
        	if("NO_USER".equals(e.getMessage())) return "noUser";
        }
        return "index";
    }
}

7、JSP 页面 index

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<html>
<head>
    <title>Title</title>
    <script src="${ctx}/static/js/jquery-1.11.1.min.js"></script>
</head>
<body style="">
<span>[<shiro:principal type="vip.sweet.smile.shiro.pojo.User" property="username"/>]的主页</span>
<a onclick="" href="javascript:" style="float: right">注销登录</a>

    <ul id="productCode">
        <li value="role:add">role:add</li>
        <li value="role:edit">role:edit</li>
        <li value="menu:add">menu:add</li>
        <shiro:hasPermission name="menu:edit"><li value="menu:edit"> menu:edit </li></shiro:hasPermission>
        <shiro:hasPermission name="dept:add"><li value="menu:edit"> dept:add </li></shiro:hasPermission>
        <shiro:hasPermission name="dept:update"><li value="source_na">dept:update</li></shiro:hasPermission>
        <li value="user:add"> user:add </li>
        <li value="user:edit">user:edit</li>
    </ul>

    <shiro:lacksPermission name="dept:update">dept:add</shiro:lacksPermission>

<div id="charts" style="width: 80%;height: 70%"></div>
<script type="text/javascript">

</script>
</body>
</html>

附:效果图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值