9.10 shiro整合thymeleaf
- 导入依赖
<!--shiro整合thymeleaf-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.1.0</version>
</dependency>
- 项目运行中其他依赖
<!--springboot整合shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.9.1</version>
</dependency>
<!--springboot整合thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--springboot-web启动-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<!--整合数据库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.7.2</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<!--非spring-boot官方-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
- 接下来需要在ShiroConfiguration配置类中整合thymeleaf
@Configuration
public class ShiroConfiguration {
//ShiroDialect thymeleaf-extras-shiro包下的Shiro方言,导入整合包后还需要进行注册
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
//第三步:ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
/*添shiro的内置过滤器,类型
anon:无需认证就可以访河
authc: 必须认证了才能让河
user: 必颈拥有记住我功能才能用
perms: 拥有对某个资源的权限才能访问:
role: 拥有某个角色权限才能访河
*/
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
/*也可以用通配符
* filterChainDefinitionMap.put("/user/*","authc");*/
//拦截简单请求
filterChainDefinitionMap.put("/user/addUser","authc");
filterChainDefinitionMap.put("/user/updUser","authc");
//设置请求的用户主体的访问权限,然后在realm给用户授予访问权限
filterChainDefinitionMap.put("/user/addUser","perms[user:add]");
filterChainDefinitionMap.put("/user/updUser","perms[user:upd]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//无认证权限时,设置登陆请求
shiroFilterFactoryBean.setLoginUrl("/user/toLogin");
//未授权时返回页面信息
shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauthorized");
return shiroFilterFactoryBean;
}
//第二步:DefaultWebSecurityManager
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//第一步:创建Realm对象,需要自定义类
@Bean
public UserRealm userRealm(){
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(new Md5CredentialsMatcher());
return userRealm;
}
}
- 自定义UserRealm,进行授权认证
package com.example.config;
import com.example.mapper.UserMapper;
import com.example.pojo.User;
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;
import org.springframework.util.StringUtils;
import javax.jws.soap.SOAPBinding;
import java.util.HashMap;
import java.util.Map;
//自定义UserRealm extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserMapper userMapper; //查询用户权限
//访问页面属于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权doGetAuthorizationInfo方法!");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//硬编码,给所有登录用户授予"user:add"权限
//info.addStringPermission("user:add");
//拿到当前用户
Subject subject = SecurityUtils.getSubject();
//1.从认证这块传递的用户信息,在授权这个用这个方法得到用户,通过当前用户Subject的属性传值
//2.也可以通过session传值
User currentUser= (User)subject.getPrincipal();
//设置用户访问授权
info.addStringPermission(currentUser.getPerm());
return info;
}
//用户登录属于认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证doGetAuthenticationInfo方法!");
//连接真实数据库
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
Map<String,String> map = new HashMap(15);
/*(String)userToken.getPrincipal() == userToken.getUsername()*/
map.put("name",userToken.getUsername());
User user = userMapper.getUser(map);
if (user==null) {
return null; //抛出UnknownAccountException异常
}
/*可以加密:
MD5加密:e10adc3949ba59abbe56e057f20f883e
MD5盐值加密(密码混合账户): e10adc3949ba59abbe56e057f20f883eusername*/
//密码认证,shiro做,加密了,默认是简单验证new SimpleCredentialsMatcher()明文验证
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
//传值方式
//1.从认证这块传递的用户信息,在授权这个用这个方法得到用户,通过当前用户Subject的属性传值
//2.也可以通过session传值
}
}
- 修改首页,拥有某权限的用户显示对应的菜单
用shiro:hasPermission=”user:add”标签来判断
- 注意命名空间的导入
xmlns:shiro=“http://www.pollix.at/thymeleaf/shiro”
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>首页</h2>
<p th:text="${msg}">信息显示</p><!--shiro:guest / shiro:notAuthenticated>--><!--th:if="${session.user == null}"-->
<shiro:notAuthenticated><a th:href="@{/user/toLogin}" >登陆</a></shiro:notAuthenticated>
<a th:href="@{/user/addUser}" shiro:hasPermission="user:add">添加</a>|<a th:href="@{/user/updUser}" shiro:hasPermission="user:upd">修改</a>|<a th:href="@{/user/logout}">退出</a>
</body>
</html>
-
这时候可以在首页添加一个登陆按钮,未登录或未认证的用户显示,登陆后或认证的用户不显示
-
方式有很多,一种是在登陆时用当前用户的session中放值。
th:if=“${session.user == null}”
@RequestMapping("/login")
public String login(String username,String password,Model model){
Subject subject = SecurityUtils.getSubject();
//全局token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
token.setRememberMe(true);
subject.login(token);
Session session = subject.getSession();
session.setAttribute("user",token.getPrincipal());
return "index";
} catch (UnknownAccountException uae) {
model.addAttribute("msg",token.getPrincipal()+" is not correct");
return "login";
} catch (IncorrectCredentialsException ice) {
model.addAttribute("msg","Password for account " + token.getPrincipal() + " was incorrect!");
return "login";
} catch (LockedAccountException lae) {
model.addAttribute("msg","The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
return "login";
}
}
- 此时便可以访问http://127.0.0.1:8080/user/进行测试了,会发现不同用户登录后显示的菜单不同,游客身份访问首页有登陆按钮。
- 访问http://127.0.0.1:8080/user/toLogin,用admin/123456登陆显示user:add权限的页面链接
- 用Tom/123456登陆显示user:upd权限的页面链接
- 另一种是用shiro的标签元素
shiro:guest shiro:notAuthenticated
- 补充:常见的Shiro 权限标签
guest标签
shiro:guest
用户没有身份验证时显示相应信息,即游客访问信息。user标签
shiro:user
</shiro:user>
用户已经身份验证/记住我登录后显示相应的信息。authenticated标签
shiro:authenticated
</shiro:authenticated>
用户已经身份验证通过,即Subject.login登录成功,不是记住我登录的。notAuthenticated标签
shiro:notAuthenticated
</shiro:notAuthenticated>
用户已经身份验证未通过,即没有调用Subject.login进行登录,包括记住我自动登录的也属于未进行身份验证。principal标签
<shiro: principal/>
<shiro:principal property=“username”/>
相当于((User)Subject.getPrincipals()).getUsername()。lacksPermission标签
<shiro:lacksPermission name=“org:create”>
</shiro:lacksPermission>
如果当前Subject没有权限将显示body体内容。hasRole标签
<shiro:hasRole name=“admin”>
</shiro:hasRole>
如果当前Subject有角色将显示body体内容。hasAnyRoles标签
<shiro:hasAnyRoles name=“admin,user”>
</shiro:hasAnyRoles>
如果当前Subject有任意一个角色(或的关系)将显示body体内容。lacksRole标签
<shiro:lacksRole name=“abc”>
</shiro:lacksRole>
如果当前Subject没有角色将显示body体内容。hasPermission标签
<shiro:hasPermission name=“user:create”>
</shiro:hasPermission>
如果当前Subject有权限将显示body体内容
下一篇:SpringBoot-35-任务
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123837.html