先导入shiro的以及thymeleaf跟shiro整合的依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- JDBC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--MySql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</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>
</dependencies>
然后写两个配置类,这里User类和service、dao层就不展示出来了
package com.lang.config;
import com.lang.pojo.User;
import com.lang.service.UserService;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了===授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
User currentUser = (User)subject.getPrincipal();//拿到User对象
info.addStringPermission(currentUser.getPerms());//添加权限,拿到权限添加进去
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken Token) throws AuthenticationException {
System.out.println("执行了===认证");
UsernamePasswordToken userToken = (UsernamePasswordToken)Token;
String username = userToken.getUsername();
Map map = new HashMap();
map.put("userName", username);
//连接真实数据库
List<User> userList = userService.selectUser(map);
if(userList.size()==0){
return null;
}
User user = userList.get(0);
//根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使用的实现类为: SimpleAuthenticationInfo
//通常需要以下四个参数
//1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.
//Object principal = user;
//2). credentials: 密码.即从数据库中获取的密码
Object credentials = user.getPassword();
//3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
String realmName = this.getName();
//4). credentialsSalt: 盐值,这里使用的是用户名
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUserName());
//密码认证,shiro做~
return new SimpleAuthenticationInfo(user,credentials,credentialsSalt,realmName);
}
}
package com.lang.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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 java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
/*
anon: 无需认证就可以访问
authc: 必须认证了才可以访问
user: 必须拥有 记住我 功能才能用
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
*/
Map<String, String> filterMap = new LinkedHashMap<>();
// filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
filterMap.put("/DigitalDictionary/primaryAdd","perms[user:add]");
filterMap.put("/DigitalDictionary/primaryEdit","perms[user:updata]");
filterMap.put("/DigitalDictionary/*","authc");
filterMap.put("/Main/*","authc");
bean.setFilterChainDefinitionMap(filterMap);
bean.setLoginUrl("/login");
//设置未授权页面
bean.setUnauthorizedUrl("/noauth");
return bean;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建Realm对象 ,需要自定义类:1
@Bean
public UserRealm userRealm(@Qualifier("hashedCredentialsMatcher")HashedCredentialsMatcher credentialsMatcher){
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(credentialsMatcher);
return userRealm;
}
//整合ShiroDialect:用来整合shiro thymeleaf
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
/**
* 凭证匹配器 告诉
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(1024);// 散列的次数,比如散列两次,相当于 md5(md5(""));
return hashedCredentialsMatcher;
}
}
Controller层的登陆
@RequestMapping("/toLogin")
public String toLogin(@RequestParam("username") String username,
@RequestParam("password") String password, Model model){
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登陆数据
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try {
subject.login(token);//执行登陆方法,如果没有异常就说明ok了
Map map = new HashMap();
map.put("userName", username);
List<User> userList = userService.selectUser(map);
User user = userList.get(0);
Session session = subject.getSession();
session.setAttribute("loginUser",user);
return "redirect:/Main/main";
} catch (UnknownAccountException e) {//用户名不存在
model.addAttribute("msg","账号错误");
return "login";
}catch (IncorrectCredentialsException e){//密码不存在
model.addAttribute("msg","密码错误");
return "login";
}
}
html的权限控制就类似于这样shiro:hasPermission=“user:add”,就是如果用户有这个添加的权限就显示出添加按钮,没有就隐藏
<div class="layui-btn-container">
<button shiro:hasPermission="user:add" class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add"> 添加 </button>
<button class="layui-btn layui-btn-sm layui-btn-danger data-delete-btn" lay-event="delete"> 删除 </button>
</div>