关于shiro的基本知识,以前的文章介绍过了,不再重复。直接上springboot+thymeleaf+shiro的集成代码。是我在项目中实际使用的,亲测可用。
1,引入依赖
注意版本,我的springboot是2.1.1.RELEASE
<!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.5</version> </dependency> <!-- shiro end --> <!--thymeleaf-shiro-extras--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
2,shiro配置
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 org.apache.shiro.mgt.SecurityManager; import java.util.LinkedHashMap; import java.util.Map; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // setLoginUrl 如未登录,跳到登录页。如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射 shiroFilterFactoryBean.setLoginUrl("/notLogin"); // 登录成功后的首页 shiroFilterFactoryBean.setSuccessUrl("/index"); // 设置无权限时跳转的 url; shiroFilterFactoryBean.setUnauthorizedUrl("/notRole"); // 设置拦截器 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // 静态资源获取,放开权限 filterChainDefinitionMap.put("/static/**", "anon"); //管理员页面,需要角色权限 “admin” filterChainDefinitionMap.put("/admin/**", "roles[admin]"); //开放登陆、注册接口 filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/api/loginCheck", "anon"); filterChainDefinitionMap.put("/api/register", "anon"); //其余接口一律拦截 // 主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 // filterChainDefinitionMap.put("/**", "authc"); filterChainDefinitionMap.put("/**", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); System.out.println("Shiro拦截器工厂类注入成功"); return shiroFilterFactoryBean; } /** * 注入 securityManager */ @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 设置realm. securityManager.setRealm(myShiroRealm()); return securityManager; } @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); // 我这里没使用cache,也可以不设置这个,只是log里会有个告警 myShiroRealm.setAuthorizationCachingEnabled(false); return myShiroRealm; } // thymeleaf页面标签需要 @Bean(name = "shiroDialect") public ShiroDialect shiroDialect(){ return new ShiroDialect(); } }
3,自定义Realm
shiro做鉴权需要三个角色,user,role,和permission
分别对应用户、角色和权限
分别创建对应的bean,然后写一下查询和插入的方法。
如
import lombok.Data; @Data public class User { private Long id; private String username; private String password; }
@Data public class Role { private int id; private String rolename; private String username; }
import com.yunsheng.filestore.entity.User; import com.yunsheng.filestore.service.RoleService; import com.yunsheng.filestore.service.UserService; 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.springframework.beans.factory.annotation.Autowired; import java.util.Set; /** * Created by yys */ //@Component("myShiroRealm") public class MyShiroRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; /** * 授权信息 */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取登录时输入的用户名 String username = (String) principalCollection.getPrimaryPrincipal(); if (username != null) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); Set<String> roles = roleService.getRoles(username); info.setRoles(roles); /** 权限还没用起来 List<String> listUrl = permissionService.getTheUrl(username);//权限 if (listUrl != null && !listUrl.isEmpty()) { for (String url : listUrl) { info.addStringPermission(url);//加入权限 } }**/ return info; } return null; } /** * 登录认证 */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String username = (String) authenticationToken.getPrincipal(); User userByUsername = userService.getUserByUsername(username); if (null == userByUsername) { return null; } // 返回一个正确的用户认证信息即可 return new SimpleAuthenticationInfo(userByUsername.getUsername(), userByUsername.getPassword(), "getName()"); } }
4,在登录鉴权时使用
/** * 登录校验 */ @RequestMapping(value = "/api/loginCheck", method = RequestMethod.POST) @ResponseBody public Map<String, Object> loginCheck(@RequestBody Map<String, String> params) { String username = params.get("username"); String password = params.get("password"); //登录后存放进shiro token UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); //根据权限,指定返回数据 boolean admin = subject.hasRole("admin"); if (admin){ // 演示可以根据权限做不同的事情 log.info("admin login"); } } catch (AuthenticationException e) { e.printStackTrace(); return ReturnApi.error("登录失败"); } return ReturnApi.success("登录成功", null); }
5,在页面上使用
html头上加上:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="Thymeleaf" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
使用:<shiro:principal/> 可显示登录的用户名
其他页面使用方法参考
<body> <h3>index</h3> <!-- 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。 --> <p shiro:guest="">Please <a href="login.html">login</a></p> <!-- 认证通过或已记住的用户。 --> <p shiro:user=""> Welcome back John! Not John? Click <a href="login.html">here</a> to login. </p> <!-- 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。 --> <p shiro:authenticated=""> Hello, <span shiro:principal=""></span>, how are you today? </p> <a shiro:authenticated="" href="updateAccount.html">Update your contact information</a> <!-- 输出当前用户信息,通常为登录帐号信息。 --> <p>Hello, <shiro:principal/>, how are you today?</p> <!-- 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。 --> <p shiro:notAuthenticated=""> Please <a href="login.html">login</a> in order to update your credit card information. </p> <!-- 验证当前用户是否属于该角色。 --> <a shiro:hasRole="admin" href="admin.html">Administer the system</a><!-- 拥有该角色 --> <!-- 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。 --> <p shiro:lacksRole="developer"><!-- 没有该角色 --> Sorry, you are not allowed to developer the system. </p> <!-- 验证当前用户是否属于以下所有角色。 --> <p shiro:hasAllRoles="developer, 2"><!-- 角色与判断 --> You are a developer and a admin. </p> <!-- 验证当前用户是否属于以下任意一个角色。 --> <p shiro:hasAnyRoles="admin, vip, developer,1"><!-- 角色或判断 --> You are a admin, vip, or developer. </p> <!--验证当前用户是否拥有指定权限。 --> <a shiro:hasPermission="userInfo:add" href="createUser.html">添加用户</a><!-- 拥有权限 --> <!-- 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。 --> <p shiro:lacksPermission="userInfo:del"><!-- 没有权限 --> Sorry, you are not allowed to delete user accounts. </p> <!-- 验证当前用户是否拥有以下所有角色。 --> <p shiro:hasAllPermissions="userInfo:view, userInfo:add"><!-- 权限与判断 --> You can see or add users. </p> <!-- 验证当前用户是否拥有以下任意一个权限。 --> <p shiro:hasAnyPermissions="userInfo:view, userInfo:del"><!-- 权限或判断 --> You can see or delete users. </p> <a shiro:hasPermission="pp" href="createUser.html">Create a new User</a> </body>