spring boot(四)shiro权限集成

时间:2022-02-04 15:16:49
<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>
<!-- shiro spring. -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
<!-- shiro ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>

默认配置请参考前言部分。

  • 创建表
DROP TABLE IF EXISTS `module`;
CREATE TABLE `module` (
`mid` int(11) NOT NULL AUTO_INCREMENT,
`mname` varchar(255) DEFAULT NULL,
PRIMARY KEY (`mid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of module
-- ----------------------------
INSERT INTO `module` VALUES ('1', 'add');
INSERT INTO `module` VALUES ('2', 'delete');
INSERT INTO `module` VALUES ('3', 'query');
INSERT INTO `module` VALUES ('4', 'update');


-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`rid` int(11) NOT NULL AUTO_INCREMENT,
`rname` varchar(255) DEFAULT NULL,
PRIMARY KEY (`rid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'admin');
INSERT INTO `role` VALUES ('2', 'customer');


-- ----------------------------
-- Table structure for module_role
-- ----------------------------
DROP TABLE IF EXISTS `module_role`;
CREATE TABLE `module_role` (
`rid` int(11) DEFAULT NULL,
`mid` int(11) DEFAULT NULL,
KEY `rid` (`rid`),
KEY `mid` (`mid`),
CONSTRAINT `mid` FOREIGN KEY (`mid`) REFERENCES `module` (`mid`),
CONSTRAINT `rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of module_role
-- ----------------------------
INSERT INTO `module_role` VALUES ('1', '1');
INSERT INTO `module_role` VALUES ('1', '2');
INSERT INTO `module_role` VALUES ('1', '3');
INSERT INTO `module_role` VALUES ('1', '4');
INSERT INTO `module_role` VALUES ('2', '1');
INSERT INTO `module_role` VALUES ('2', '3');





-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'hlhdidi', '123');
INSERT INTO `user` VALUES ('2', 'xyycici', '1992');

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`uid` int(11) DEFAULT NULL,
`rid` int(11) DEFAULT NULL,
KEY `u_fk` (`uid`),
KEY `r_fk` (`rid`),
CONSTRAINT `r_fk` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`),
CONSTRAINT `u_fk` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', '1');
INSERT INTO `user_role` VALUES ('2', '2');
  • 创建实体类:
    User 类:
@Entity
public class User {
private int uid;
private String username;
private String password;
private Set<Role> roleList;

@Id
@Column(name = "uid")
public int getUid() {
return uid;
}

public void setUid(int uid) {
this.uid = uid;
}

@Basic
@Column(name = "username")
public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

@Basic
@Column(name = "password")
public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_role", joinColumns = { @JoinColumn(name = "rid") }, inverseJoinColumns = {
@JoinColumn(name = "uid") })
public Set<Role> getRoleList() {
return roleList;
}

public void setRoleList(Set<Role> roleList) {
this.roleList = roleList;
}

}

Role类:

@Entity
public class Role {
private int rid;
private String rname;
private Set<Module> moduleList;

@Id
@Column(name = "rid")
public int getRid() {
return rid;
}

public void setRid(int rid) {
this.rid = rid;
}

@Basic
@Column(name = "rname")
public String getRname() {
return rname;
}

public void setRname(String rname) {
this.rname = rname;
}

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "module_role", joinColumns = { @JoinColumn(name = "rid") }, inverseJoinColumns = {
@JoinColumn(name = "mid") })
public Set<Module> getModuleList() {
return moduleList;
}

public void setModuleList(Set<Module> moduleList) {
this.moduleList = moduleList;
}

}

Module类:

@Entity
public class Module {
private int mid;
private String mname;

@Id
@Column(name = "mid")
public int getMid() {
return mid;
}

public void setMid(int mid) {
this.mid = mid;
}

@Basic
@Column(name = "mname")
public String getMname() {
return mname;
}

public void setMname(String mname) {
this.mname = mname;
}

}
  • 创建dao
public interface UserRepository extends JpaRepository<User, Integer> {
User findByUsername(String username);
}
  • 创建shiro的配置类及验证类:
  • AuthRealm
public class AuthRealm extends AuthorizingRealm {
@Autowired
private UserService userService;

// 认证.登录
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken utoken = (UsernamePasswordToken) token;// 获取用户输入的token
String username = utoken.getUsername();
User user = userService.getUser(username);
return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());// 放入shiro.调用CredentialsMatcher检验密码
}

// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
User user = (User) principal.fromRealm(this.getClass().getName()).iterator().next();// 获取session中的用户
List<String> permissions = new ArrayList<>();
Set<Role> roles = user.getRoleList();
if (roles.size() > 0) {
for (Role role : roles) {
Set<Module> modules = role.getModuleList();
if (modules.size() > 0) {
for (Module module : modules) {
permissions.add(module.getMname());
}
}
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);// 将权限放入shiro中.
return info;
}

}

CredentialsMatcher类:

public class CredentialsMatcher extends SimpleCredentialsMatcher {

@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
UsernamePasswordToken utoken = (UsernamePasswordToken) token;
// 获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
String inPassword = new String(utoken.getPassword());
// 获得数据库中的密码
String dbPassword = (String) info.getCredentials();
// 进行密码的比对
return this.equals(inPassword, dbPassword);
}

}

ShiroConfiguration配置类:

@Configuration
public class ShiroConfiguration {
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(manager);
// 配置登录的url和登录成功的url
bean.setLoginUrl("/login");
bean.setSuccessUrl("/home");
// 配置访问权限
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/jsp/login.jsp*", "anon"); // 表示可以匿名访问
filterChainDefinitionMap.put("/loginUser", "anon");
filterChainDefinitionMap.put("/logout*", "anon");
filterChainDefinitionMap.put("/jsp/error.jsp*", "anon");
filterChainDefinitionMap.put("/jsp/index.jsp*", "authc");
filterChainDefinitionMap.put("/*", "authc");// 表示需要认证才可以访问
filterChainDefinitionMap.put("/**", "authc");// 表示需要认证才可以访问
filterChainDefinitionMap.put("/*.*", "authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}

// 配置核心安全事务管理器
@Bean(name = "securityManager")
public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
System.err.println("--------------shiro已经加载----------------");
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(authRealm);
return manager;
}

// 配置自定义的权限登录器
@Bean(name = "authRealm")
public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
AuthRealm authRealm = new AuthRealm();
authRealm.setCredentialsMatcher(matcher);
return authRealm;
}

// 配置自定义的密码比较器
@Bean(name = "credentialsMatcher")
public CredentialsMatcher credentialsMatcher() {
return new CredentialsMatcher();
}

@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
@Qualifier("securityManager") SecurityManager manager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(manager);
return advisor;
}
}
  • 创建service类;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;

public User getUser(String name) {
return userRepository.findByUsername(name);
}

}
  • 创建controller类:
@RestController
public class IndexWeb {
private Logger logger = LoggerFactory.getLogger(getClass());

@RequestMapping("/index")
public String index() {
logger.info("index:" + System.currentTimeMillis());
return "Hello";
}

@RequestMapping("/login")
public String login() throws JSONException {
JSONObject out = new JSONObject();
out.put("code", "-101");
out.put("message", "no permission,please login or confirm your permission");
return out.toString();
}

@RequestMapping("/loginUser")
public String loginUser(String username, String password, HttpSession session) {
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(usernamePasswordToken); // 完成登录
User user = (User) subject.getPrincipal();
session.setAttribute("user", user);
return "index";
} catch (Exception e) {
return "loginError";// 返回登录页面
}

}

@RequestMapping("/logOut")
public String logOut(HttpSession session) {
Subject subject = SecurityUtils.getSubject();
subject.logout();
// session.removeAttribute("user");
return "login";
}

}

OK,主要程序和配置都已经完成。启动程序。访问http://localhost:8080/index 报错没有权限
http://localhost:8080/loginUser?username=XXX&password=xxx
登陆成功之后在访问首页,就OK
项目地址:
https://git.oschina.net/xzwei/spring_cloud.git