• sb_shiro_session
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.20.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.huarui</groupId>
<artifactId>sb_shiro_session</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sb_shiro_session</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.crazycake/shiro-redis -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> <repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories> </project>

pom.xml

server.port=8089

#thymeleaf
spring.thymeleaf.cache=false #redis
spring.redis.host=39.108.85.204
spring.redis.port=6379 #shiro redis
shiro.redis.host=39.108.85.204:6379
shiro.redis.timeout=1800000 #mysql
spring.datasource.url=jdbc:mysql://39.108.85.204:3306/mybatis?useUnicode=true&characterEncoding=utf8
spring.datasource.username=youxiu326
spring.datasource.password=zz123456.ZZ
spring.datasource.driver-class-name=com.mysql.jdbc.Driver #jpa
spring.jpa.database = MYSQL
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

application.properties

  • entity
/**
* Created by lihui on 2019/1/29.
*
* 用户登录 通过 code+password
*
*/
@Entity
@Table(name="sys_operator")
public class Operator implements Serializable{ private String id; private String name; private String code; private String password; /**
* 拥有角色
*/
private List<Role> roles; @ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "sys_operator_role", joinColumns = {
@JoinColumn(name = "operator_id", referencedColumnName = "id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id", referencedColumnName = "id") })
public List<Role> getRoles() {
return roles;
} public void setRoles(List<Role> roles) {
this.roles = roles;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Id
@GeneratedValue(generator = "sys_uid")
@GenericGenerator(name = "sys_uid", strategy = "uuid")
public String getId() {
return id;
} public void setId(String id) {
this.id = id;
}
}

Operator(用户)

/**
* Created by lihui on 2019/1/29.
* 角色
*/
@Entity
@Table(name="sys_role")
public class Role implements Serializable { private String id; /**
* 角色
*/
private String name; /**
* 角色拥有资源
*/
private List<Resource> resources; @Id
@GeneratedValue(generator = "sys_uid")
@GenericGenerator(name = "sys_uid", strategy = "uuid")
public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} @ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "sys_role_resource", joinColumns = {
@JoinColumn(name = "role_id", referencedColumnName = "id") },
inverseJoinColumns = {@JoinColumn(name = "resource_id", referencedColumnName = "id") })
public List<Resource> getResources() {
return resources;
} public void setResources(List<Resource> resources) {
this.resources = resources;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

Role(角色)

package com.huarui.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.GenericGenerator; import javax.persistence.*;
import java.io.Serializable;
import java.util.List; /**
* Created by lihui on 2019/1/29.
* 资源
*/
@Entity
@Table(name="sys_resource")
public class Resource implements Serializable{ private String id; /**
* 权限名称
*/
private String name; /**
* 权限URL
*/
private String url; /**
* 是否需要授权
*/
private boolean authorization; /**
* 上级权限
*/
private Resource parent; /**
* 下级权限
*/
private List<Resource> children; @Id
@GeneratedValue(generator = "sys_uid")
@GenericGenerator(name = "sys_uid", strategy = "uuid")
public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public boolean isAuthorization() {
return authorization;
} public void setAuthorization(boolean authorization) {
this.authorization = authorization;
} @ManyToOne
@JoinColumn(name = "parent_id")
@JsonIgnore
public Resource getParent() {
return parent;
} public void setParent(Resource parent) {
this.parent = parent;
} /**
* 级联删除
* @return
*/
@OneToMany(cascade={CascadeType.REMOVE},mappedBy = "parent")
public List<Resource> getChildren() {
return children;
} public void setChildren(List<Resource> children) {
this.children = children;
}
}

Resource(资源)

一个用户拥有多个角色 一个角色可以访问多个资源

表数据

sys_operato
"id" "code" "name" "password"
"402882ec689886fa016898875c2d0000" "admin" "lihui" "c6cc583c2703c6271ff04981e6225f0f"
"402882ec6898b30b016898b35a610000" "test" "test" "4de0fe9cf9f47ce5af891d6182d6c4b7"
"402882ec6898ddf0016898de59f10000" "open" "open" "cba0efa9a832d0cf2e1a646db406bdfa" sys_role
"id" "name"
"1" "admin"
"2" "test" sys_operator_role
"operator_id" "role_id"
"402882ec689886fa016898875c2d0000" "1"
"402882ec6898b30b016898b35a610000" "2" sys_resource
"id" "authorization" "name" "url" "parent_id"
"1" "1" "添加用户" "/to/add" ""
"2" "1" "修改用户" "/to/update" ""
"3" "1" "用户列表" "/to/list" "" sys_role_resource
"role_id" "resource_id"
"1" "1"
"1" "2"
"1" "3"
"2" "3"
  • dao
public interface RoleDao extends JpaRepository<Role, String> {

}

RoleDao

public interface ResourceDao extends JpaRepository<Resource, String> {

    @Query("select distinct r.resources from Operator as o left join o.roles as r where o.id = ?1")
public List<Resource> findResourcesByOperator(String operatorId); @Query("from Resource where authorization=true ")
public List<Resource> findAllByAutho(); }

ResourceDao

public interface OperatorDao extends JpaRepository<Operator, String> {

    Operator findByCode(String code);

}

OperatorDao

  • service
public interface OperatorService {

    Operator findByCode(String code);

    void save(Operator operator);

}

@Service
public class OperatorServiceImpl implements OperatorService { @Autowired
private OperatorDao operatorDao; @Override
public Operator findByCode(String code) {
return operatorDao.findByCode(code);
} @Override
public void save(Operator operator) {
operatorDao.save(operator);
}
}

OperatorService

public interface ResourceService {

    List<Resource> getResourcesByOperator(String operatorId);

    List<Resource> findAllByAutho();

}

@Service
public class ResourceServiceImpl implements ResourceService { @Autowired
private ResourceDao resourceDao; @Override
public List<Resource> getResourcesByOperator(String operatorId) {
return resourceDao.findResourcesByOperator(operatorId);
} @Override
public List<Resource> findAllByAutho() {
return resourceDao.findAllByAutho();
}
}

ResourceService

  • controller
package com.huarui.controller;

import com.huarui.entity.Operator;
import com.huarui.service.OperatorService;
import com.huarui.utils.PasswordUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import java.util.HashMap;
import java.util.Map; /**
* Created by lihui on 2019/1/29.
*/
@Controller
@RequestMapping("/")
public class LoginController { @Autowired
private OperatorService operatorService; @RequestMapping("/")
public String tologin(){
return "login";
} @RequestMapping("/login") //未登录自动跳至login
public String login(){
return "login";
} @RequestMapping("/403") //没有权限自动跳至403
public String to403(){
return "403";
} /**
* 跳转至指定页面
* @param path
* @return
*/
@GetMapping("/to/{url}")
public String path(@PathVariable("url")String path){
return path;
} @PostMapping("/ajax")
public @ResponseBody Map ajax(){
Map map = new HashMap<>();
map.put("state","200");
map.put("msg","成功获取到数据");
map.put("data","youxiu326@163.com");
return map;
} /**
* 登录
* @param operator
* @return
*/
@RequestMapping("/loginAction")
public @ResponseBody String loginAction(Operator operator){
if (StringUtils.isBlank(operator.getCode())){
return "编号不能为空";
}
if (StringUtils.isBlank(operator.getPassword())){
return "密码不能为空";
}
UsernamePasswordToken token = new UsernamePasswordToken(operator.getCode(), operator.getPassword());
Subject subject = SecurityUtils.getSubject();
subject.login(token);
return "登录成功";
} /**
* 注册
* @param operator
* @return
*/
@RequestMapping("/register")
public @ResponseBody String register(Operator operator){ //TODO 编号重复验证 if (StringUtils.isBlank(operator.getName())){
return "昵称不能为空";
}
if (StringUtils.isBlank(operator.getCode())){
return "编号不能为空";
}
if (StringUtils.isBlank(operator.getPassword())){
return "密码不能为空";
}
operator.setPassword(PasswordUtil.saltAndMd5(operator.getPassword(),operator.getName(),2));
operatorService.save(operator);
return "注册成功";
}
}
  • utils
/**
* Created by lihui on 2019/1/29.
* MD5加密工具类
*/
public class PasswordUtil { /**
* @param password 需要加密的次数
* @param username 盐
* @param hashIterations 加密次数
* @return
*/
public static String saltAndMd5(String password,String username,int hashIterations){
//加密算法
String algorithmName = "MD5";
//盐值
Object salt = ByteSource.Util.bytes(username); SimpleHash hash = new SimpleHash(algorithmName, password, salt, hashIterations);
return hash.toString();//32位
}
}

PasswordUtil

  • config
package com.huarui.config;

import com.huarui.entity.Operator;
import com.huarui.entity.Resource;
import com.huarui.service.ResourceService;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; import javax.servlet.ServletRequest;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; /**
* Created by lihui on 2019/1/29.
* 实现session共享
* shiro配置类
*/
@Configuration
public class ShiroConfig { @Value("${shiro.redis.host}")
public String host; @Value("${shiro.redis.timeout}")
public int timeout; @Autowired
private ResourceService resourceService; //shiro共享session 参考博客: https://www.cnblogs.com/LUA123/p/9337963.html /*
过滤器
anon:所有url都都可以匿名访问
authc: 需要认证才能进行访问
user:配置记住我或认证通过可以访问
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager); //拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/jquery-1.11.3.min.js", "anon");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/loginAction", "anon");
filterChainDefinitionMap.put("/register", "anon");
//配置退出 过滤器,其中的具体的退出代码shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout"); //<!-- 过滤链定义,从上向下顺序执行,一般将*//**放在最为下边 -->
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//TODO 添加权限拦截
List<Resource> resources = resourceService.findAllByAutho();
for(Resource re : resources){
filterChainDefinitionMap.put(re.getUrl(), String.format("perms[%s]", re.getUrl()));
}
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.html"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
//自定义拦截器
//shiroFilterFactoryBean.getFilters().put("authc", new SimpleFormAuthenticationFilter());
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
} /**
* 自定义 认证 授权
*/
@Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
} /**
* 4. 配置LifecycleBeanPostProcessor,可以来自动的调用配置在Spring IOC容器中 Shiro Bean 的生命周期方法
* //TODO 该方法指定为static 否则无法初始化@Value
* 参考博客: https://blog.csdn.net/wuxuyang_7788/article/details/70141812
* @return
*/
@Bean
public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
} /**
* 5. 启用IOC容器中使用Shiro的注解,但是必须配置第四步才可以使用
*
* @return
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
} /**
* 密码校验器
*/
@Bean
public CredentialsMatcher myCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");//MD5加密
credentialsMatcher.setHashIterations(2);//加密两次
return credentialsMatcher;
} /**
* 配置SecurityManager
*
*/
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm()); // 设置realm
securityManager.setSessionManager(sessionManager()); // 设置sessionManager
// securityManager.setCacheManager(redisCacheManager()); // 配置缓存的话,退出登录的时候crazycake会报错,要求放在session里面的实体类必须有个id标识
return securityManager;
} /**
* redis 管理器
* @return
*/
@Bean
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager(); // crazycake 实现
redisManager.setHost(host);
redisManager.setTimeout(timeout);
return redisManager;
} /**
* 缓存管理器
* @return
*/
@Bean
public RedisCacheManager redisCacheManager() {
RedisCacheManager cacheManager = new RedisCacheManager(); // crazycake 实现
cacheManager.setRedisManager(redisManager());
return cacheManager;
} /**
* session dao 持久到redis
* @return
*/
@Bean
public RedisSessionDAO sessionDAO() {
RedisSessionDAO sessionDAO = new RedisSessionDAO(); // crazycake 实现
sessionDAO.setRedisManager(redisManager());
sessionDAO.setSessionIdGenerator(new JavaUuidSessionIdGenerator()); // Session ID 生成器
return sessionDAO;
} @Bean
public SimpleCookie cookie() {
SimpleCookie cookie = new SimpleCookie("SHAREJSESSIONID"); // cookie的name,对应的默认是 JSESSIONID
cookie.setHttpOnly(true);
cookie.setPath("/"); // path为 / 用于多个系统共享JSESSIONID
return cookie;
} /**
* session 默认管理器
* @return
*/
@Bean
public DefaultWebSessionManager sessionManager() {
//解决doReadSession多次访问
DefaultWebSessionManager sessionManager = new CustomDefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(timeout); // 设置session超时
sessionManager.setDeleteInvalidSessions(true); // 删除无效session
sessionManager.setSessionIdCookie(cookie()); // 设置JSESSIONID
sessionManager.setSessionDAO(sessionDAO()); // 设置sessionDAO
return sessionManager;
} /**
* 配置RedisTemplate,充当数据库服务
* @return
*/
@Bean
public RedisTemplate<String, Operator> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Operator> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Operator>(Operator.class));
return redisTemplate;
} /**
* 解决doReadSession多次访问问题
*
*/
public static class CustomDefaultWebSessionManager extends DefaultWebSessionManager{
@Override
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
Serializable sessionId = getSessionId(sessionKey);
if(sessionId == null){
return super.retrieveSession(sessionKey);
}
ServletRequest request = WebUtils.getRequest(sessionKey);
Object sessionObj = request.getAttribute(sessionId.toString());
if (sessionObj != null) {
return (Session) sessionObj;
}
Session s = super.retrieveSession(sessionKey);
if (request != null && null != sessionId) {
request.setAttribute(sessionId.toString(), s);
}
return s;
}
} }

ShiroConfig

package com.huarui.config;

import com.huarui.entity.Operator;
import com.huarui.entity.Resource;
import com.huarui.service.OperatorService;
import com.huarui.service.ResourceService;
import com.huarui.utils.PasswordUtil;
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.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /**
* Created by lihui on 2019/1/29.
*
* 自定义Realm
*/
public class MyShiroRealm extends AuthorizingRealm{ @Autowired
private OperatorService operatorService; @Autowired
private ResourceService resourceService; //授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//取出当前登录用户
Operator operator = (Operator) principalCollection.getPrimaryPrincipal();
//获得当前登录用户所拥有的所有资源
List<Resource> resources = resourceService.getResourcesByOperator(operator.getId());
if(resources!=null && resources.size()>0){
for(Resource p:resources){
authorizationInfo.addStringPermission(p.getUrl());//添加权限
}
} return authorizationInfo;
} //认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取用户编号 与密码
UsernamePasswordToken upToken = (UsernamePasswordToken)authenticationToken;
String usercode = (String)upToken.getPrincipal();
String password = String.valueOf(upToken.getPassword());
Operator operator = operatorService.findByCode(usercode);
if (operator==null){
throw new AuthenticationException("用户编号不存在");
}else if(!operator.getPassword().equals(PasswordUtil.saltAndMd5(password,operator.getName(),2))){
throw new AuthenticationException("密码不正确");
}
//返回认证信息由父类 进行认证
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
operator, //用户名
password, //密码
ByteSource.Util.bytes(operator.getName()),//盐
getName() //realm name
);
return authenticationInfo;
} //清空shiro缓存的权限
public void clearAuthz(){
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
}
}

MyShiroRealm

  • html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" >
<head>
<base th:href="${#httpServletRequest.getContextPath()+'/'}">
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body> <h3>这是登录页面</h3> <form action="loginAction">
编号:<input name="code"/>
<br/>
密码:<input name="password"/>
<br/>
<input type="submit" value="登录">
</form> <br/> <a href="logout" target="_blank">登出</a> <br/>
<br/>
<br/> <form action="register">
姓名:<input name="name"/>
<br/>
编号:<input name="code"/>
<br/>
密码:<input name="password"/>
<br/>
<input type="submit" value="注册">
</form> <br/>
<a href="/to/add" target="_blank">去添加界面(admin角色可以访问)</a>
<br/>
<a href="/to/update" target="_blank">去修改界面(admin角色可以访问)</a>
<br/>
<a href="/to/list" target="_blank">去列表界面(admin和test 角色可以访问)</a>
<br/>
<a href="/to/open" target="_blank">去开放界面(登录了可以访问)</a>
<br/> </body> </html>
<br/>
<a href="/to/add" target="_blank">去添加界面(admin角色可以访问)</a>
<br/>
<a href="/to/update" target="_blank">去修改界面(admin角色可以访问)</a>
<br/>
<a href="/to/list" target="_blank">去列表界面(admin和test 角色可以访问)</a>
<br/>
<a href="/to/open" target="_blank">去开放界面(登录了可以访问)</a>
<br/> 说明: //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//TODO 添加权限拦截
List<Resource> resources = resourceService.findAllByAutho();
for(Resource re : resources){
filterChainDefinitionMap.put(re.getUrl(), String.format("perms[%s]", re.getUrl()));
}
filterChainDefinitionMap.put("/**", "authc"); 所有的resources资源需要拥有权限才能访问,
如果资源表中不存在的,则登录就可以访问 看表
1 1 添加用户 /to/add
2 1 修改用户 /to/update
3 1 用户列表 /to/list 【/to/open】不存在资源表中,所以登录就可以访问 admin用户 拥有admin角色 可以访问【列表上的所有资源】
test用户 拥有test角色 可以访问【/to/list】

测试1: 不登录情况下 所有a标签进入不了,

测试2: 登录test用户pwd:111111 可以访问去列表界面 去开放界面

测试3:登录admin用户pwd:111111 可以访问列出的所有界面

github: https://github.com/youxiu326/sb_shiro_session.git

springboot+shiro 01 - 实现权限控制的更多相关文章

  1. JAVAEE——BOS物流项目11:在realm中授权、shiro的方法注解权限控制、shiro的标签权限控制、总结shiro的权限控制方式、权限管理

    1 学习计划 1.在realm中进行授权 2.使用shiro的方法注解方式权限控制 n 在spring文件中配置开启shiro注解支持 n 在Action方法上使用注解 3.★使用shiro的标签进行 ...

  2. 1、 Shiro框架:认证,授权(验权 2. Shiro框架实现权限控制方式:

    1. Shiro框架:认证,授权(验权) a) 认证逻辑:applicationCode—>通过工具类获取subject对象,调用login方法参数令牌信息->安全管理器------> ...

  3. springmvc+spring+mybatis+maven项目集成shiro进行用户权限控制【转】

    项目结构:   1.maven项目的pom中引入shiro所需的jar包依赖关系 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...

  4. shiro框架的四中权限控制方式

    https://www.cnblogs.com/cocosili/p/7103025.html 一.在自定义的realm中进行权限控制 在applicationContext.xml文件中添加  /a ...

  5. Spring Boot + Spring Cloud 实现权限管理系统 权限控制(Shiro 注解)

    技术背景 当前,我们基于导航菜单的显示和操作按钮的禁用状态,实现了页面可见性和操作可用性的权限验证,或者叫访问控制.但这仅限于页面的显示和操作,我们的后台接口还是没有进行权限的验证,只要知道了后台的接 ...

  6. Spring Boot + Spring Cloud 实现权限管理系统 后端篇(二十四):权限控制(Shiro 注解)

    在线演示 演示地址:http://139.196.87.48:9002/kitty 用户名:admin 密码:admin 技术背景 当前,我们基于导航菜单的显示和操作按钮的禁用状态,实现了页面可见性和 ...

  7. 单点登录(十八)----cas4.2.x客户端增加权限控制shiro

    我们在上面章节已经完成了cas4.2.x登录启用mongodb的验证方式. 单点登录(十三)-----实战-----cas4.2.X登录启用mongodb验证方式完整流程 也完成了获取管理员身份属性 ...

  8. 论Java访问权限控制的重要性

    人在什么面前最容易失去抵抗力? 美色,算是一个,比如说西施的贡献薄就是忍辱负重.以身报国.助越灭吴:金钱,算是另外一个,我们古人常说“钱乃身外之物,生不带来死不带去”,但我们又都知道“有钱能使鬼推磨” ...

  9. shiro实现动态权限管理

    用到shiro框架实现权限控制时,根据实际要求,权限在数据库增删改后都要把权限过滤链变化实时更新到服务器中. 1.配置文件里配置的filterchains都是静态的,但实际开发中更多的是从数据库中动态 ...

随机推荐

  1. 如何将csf ip 端口映射

    csf基于iptables的,不支持SNAT外,其他映射是支持的.最新版不知道,有没有解决这个问题.配置文件/etc/csf.allow 1,DNAT 用法: IPx|*|IPy|*|tcp/udp ...

  2. 【C# 线程】内存屏障 MemoryBarrier

    背景 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thread.Vo ...

  3. CVE-2022-22947 Spring Cloud Gateway SPEL RCE复现

    目录 0 环境搭建 1 漏洞触发点 2 构建poc 3 总结 参考 0 环境搭建 影响范围: Spring Cloud Gateway 3.1.x < 3.1.1 Spring Cloud Ga ...

  4. [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器---(8) ---Distributed Hash之后向传播

    [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器---(8) ---Distributed Hash之后向传播 目录 [源码解析] NVIDIA HugeCTR,GPU 版本参数服务 ...

  5. idea教程--Maven 骨架介绍

    简单的说,Archetype是Maven工程的模板工具包.一个Archetype定义了要做的相同类型事情的初始样式或模型.这个名称给我们提供来了一个一致的生成Maven工程的方式.Archetype会 ...

  6. Java课程设计---安装Mysql及管理工具

    1.安装mysql 没有安装包的可以在这个地址下载:https://dev.mysql.com/downloads/mysql/5.5.html 双击提供的安装包 (安装路径可以不用更改) 在弹出的窗 ...

  7. VS常用的快捷键

    整理代码          Ctrl+k+f 注释                 Ctrl+k+c 取消注释          Ctrl+k+u 帮助文档          F1 无调试启动     ...

  8. SQL Server的Linked Servers(链接)

    我们在使用SQL Server时,有时会有这种需求,需要从一个SQL Server服务器A中,查询另一个SQL Server服务器B中的表,然后将SQL Server服务器A中的表和SQL Serve ...

  9. (六)React Ant Design Pro + .Net5 WebApi:后端环境搭建-EF Core

    一. 简介 EFCore 是轻量化.可扩展.开源和跨平台版的常用数据访问技术,走你(官方文档) 二. 使用 1.安装数据库驱动包.PMC 工具包 不同的数据库有不同的包,参考,我用 PostgreSQ ...

  10. linux作业--第十一周

    1. 导入hellodb.sql生成数据库 (1) 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄 (2) 以ClassID为分组依据,显示每组的平均年龄 (3) 显示第2题中 ...