SpringBoot+Thymeleaf+Shiro整合
阿新 • • 發佈:2021-02-07
技術標籤:javashirospring boot
SpringBoot+Thymeleaf+Shiro整合
pom.xml
<!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
user.java(使用者實體類):
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.lamda.shiro.Role; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Set; @Data @AllArgsConstructor @NoArgsConstructor @TableName(value = "t_tzsb_user") public class UserEntity { //id @TableId(type = IdType.AUTO) private Integer id; //使用者名稱 private String userName; //密碼 private String passWord; //部門 private String department; //郵箱 private String mail; //角色名稱 private String roleName; }
Role.java(角色對應實體類):
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; import java.math.BigDecimal; import java.util.Set; /** * <p> * * </p> * * @author qcl * @since 2021-02-04 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("T_TZSB_ROLE") public class Role implements Serializable { private static final long serialVersionUID = 1L; /** * id */ @TableId(type = IdType.AUTO) private Integer id; /** * 角色名稱 */ @TableField("ROLE_NAME") private String roleName; /** * 使用者ID */ @TableField("USER_ID") private Integer userId; }
Permissions.java(許可權對應實體類):
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author qinchunlin
* @version 1.0.0
* @ClassName Permissions
* @Description
* @createTime 2021年01月09日 10:17:00
*/
@Data
@AllArgsConstructor
@TableName("T_TZSB_PERMISSIONS")
public class Permissions {
@TableId(type = IdType.AUTO)
private Integer id;
private String permissionsName;
private Integer roleId;
}
CustomRealm.java
- 自定義Realm用於查詢使用者的角色和許可權資訊並儲存到許可權管理器
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lamda.entity.yhgl.UserEntity;
import com.lamda.service.qt.RoleService;
import com.lamda.service.yhgl.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 org.springframework.util.StringUtils;
public class CustomRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
/**
* @MethodName doGetAuthorizationInfo
* @Description 許可權配置類
* @Param [principalCollection]
* @Return AuthorizationInfo
* @Author WangShiLin
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//獲取登入使用者名稱
String name = (String) principalCollection.getPrimaryPrincipal();
//查詢使用者名稱稱
UserEntity user = userService.getUserByName(name);
//新增角色和許可權
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
Role role=roleService.getOne(new QueryWrapper<Role>().eq("ROLE_NAME",user.getRoleName()));
//新增角色
simpleAuthorizationInfo.addRole(role.getRoleName());
//新增許可權
for (Permissions permissions : userService.getPermissions(role.getId())) {
simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
}
return simpleAuthorizationInfo;
}
/**
* @MethodName doGetAuthenticationInfo
* @Description 認證配置類
* @Param [authenticationToken]
* @Return AuthenticationInfo
* @Author WangShiLin
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
return null;
}
//獲取使用者資訊
String name = authenticationToken.getPrincipal().toString();
UserEntity user = userService.getUserByName(name);
if (user == null) {
//這裡返回後會報出對應異常
return null;
} else {
//這裡驗證authenticationToken和simpleAuthenticationInfo的資訊
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassWord(), getName());
return simpleAuthenticationInfo;
}
}
}
ShiroConfig.java
- 把CustomRealm和SecurityManager等注入到spring容器中
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author qinchunlin
* @version 1.0.0
* @ClassName shiroConfig
* @Description
* @createTime 2021年01月09日 10:30:00
*/
@Configuration
public class ShiroConfig {
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
//將自己的驗證方式加入容器
@Bean
public CustomRealm myShiroRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
//許可權管理,配置主要是Realm的管理認證
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工廠,設定對應的過濾條件和跳轉條件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> map = new HashMap<>();
//登出
map.put("/user/logout", "logout");
//忽略靜態資源
map.put("/**/*.css", "anon");
map.put("/**/*.js", "anon");
map.put("/**/*.html", "anon");
map.put("/**/*.conf", "anon");
//對所有使用者認證
map.put("/**", "anon");
//登入
shiroFilterFactoryBean.setLoginUrl("/login");
//首頁
shiroFilterFactoryBean.setSuccessUrl("/ggts/getGgts");
//錯誤頁面,認證不通過跳轉
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* 頁面上使用shiro標籤
* @return
*/
@Bean(name = "shiroDialect")
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
}
全域性異常處理
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@[email protected]
public class MyExceptionHandler {
@ExceptionHandler
@ResponseBody
public String ErrorHandler(AuthorizationException e) {
log.error("沒有通過許可權驗證!", e);
return "沒有通過許可權驗證!";
}}
後端控制權限
- 這兩個註解可以放在類上或方法上
@RequiresRoles("admin")
@RequiresPermissions("query")
前端使用shiro標籤(兩種方式)(使用thymeleaf時)