下面是一个简单的springBoot集成shrio的项目,技术是:spring boot+idea+gradle+shrio+mybatis
1:首先在build.gradle中导入依赖
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE')
}
}
group "com.li"
version "1.0-SNAPSHOT"
apply plugin: "java" //java 插件
apply plugin: "org.springframework.boot" //spring boot 插件
apply plugin: "io.spring.dependency-management" apply plugin: "application" //应用
//mainClassName = "com.li.SpringBootShrioManaApplication"
sourceCompatibility = 1.8 repositories {
mavenCentral()
} dependencies {
compile("org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-activemq",
"org.springframework.boot:spring-boot-starter-test",
"org.springframework.boot:spring-boot-starter-cache",
"org.springframework.boot:spring-boot-devtools",
"mysql:mysql-connector-java:5.1.35",
'org.apache.commons:commons-lang3:3.4',
'org.apache.commons:commons-pool2',
"org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.0",
'org.apache.shiro:shiro-core:1.2.2',
'org.apache.shiro:shiro-spring:1.2.2',
'org.apache.shiro:shiro-ehcache:1.2.2',
'org.apache.logging.log4j:log4j-core:2.7'
)
testCompile group: 'junit', name: 'junit', version: '4.12'
}
2:创建sql表并导入数据。
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 ('', 'add');
INSERT INTO `module` VALUES ('', 'delete');
INSERT INTO `module` VALUES ('', 'query');
INSERT INTO `module` VALUES ('', 'update'); -- ----------------------------
-- 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 ('', '');
INSERT INTO `module_role` VALUES ('', '');
INSERT INTO `module_role` VALUES ('', '');
INSERT INTO `module_role` VALUES ('', '');
INSERT INTO `module_role` VALUES ('', '');
INSERT INTO `module_role` VALUES ('', ''); -- ----------------------------
-- 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 ('', 'admin');
INSERT INTO `role` VALUES ('', 'customer'); -- ----------------------------
-- 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 ('', 'hlhdidi', '');
INSERT INTO `user` VALUES ('', 'xyycici', ''); -- ----------------------------
-- 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 ('', '');
INSERT INTO `user_role` VALUES ('', '');
3:创建dao层pojo和mapper映射
package com.li.dao.pojo; import java.util.Set; public class Module {
private Integer mid;
private String mname;
private Set<Role> roles; public Integer getMid() {
return mid;
} public void setMid(Integer mid) {
this.mid = mid;
} public String getMname() {
return mname;
} public void setMname(String mname) {
this.mname = mname;
} public Set<Role> getRoles() {
return roles;
} public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
package com.li.dao.pojo; import java.util.HashSet;
import java.util.Set; public class Role {
private Integer rid;
private String rname;
private Set<User> users = new HashSet<>();
private Set<Module> modules = new HashSet<>(); public Integer getRid() {
return rid;
} public void setRid(Integer rid) {
this.rid = rid;
} public String getRname() {
return rname;
} public void setRname(String rname) {
this.rname = rname;
} public Set<User> getUsers() {
return users;
} public void setUsers(Set<User> users) {
this.users = users;
} public Set<Module> getModules() {
return modules;
} public void setModules(Set<Module> modules) {
this.modules = modules;
}
}
package com.li.dao.pojo; import java.io.Serializable;
import java.util.HashSet;
import java.util.Set; public class User implements Serializable {
private Integer uid;
private String username;
private String password;
private Set<Role> roles = new HashSet<>(); public Integer getUid() {
return uid;
} public void setUid(Integer uid) {
this.uid = uid;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public Set<Role> getRoles() {
return roles;
} public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
UserMapper.java
package com.li.dao.Mapper; import com.li.dao.pojo.User;
import org.springframework.stereotype.Repository; @Repository
public interface UserMapper {
public User findByUserName(String username);
}
4:创建service层,UserService.java,UserServiceImpl.java
package com.li.service; import com.li.dao.pojo.User; public interface UserService {
User findUserByName(String username);
}
package com.li.service.impl; import com.li.dao.Mapper.UserMapper;
import com.li.dao.pojo.User;
import com.li.service.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class UserServiceImpl implements UserService{
Logger logger = LogManager.getLogger(UserServiceImpl.class);
@Autowired
private UserMapper userMapper;
@Override
public User findUserByName(String username) {
logger.warn(username);
return userMapper.findByUserName(username);
}
}
5:配置controller层
package com.li.controller; import com.li.dao.pojo.User;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession;
import java.lang.reflect.Method; @Controller
public class LoginController { Logger logger= LogManager.getLogger(LoginController.class);
@RequestMapping("/loginTest")
public String login() {
return "login.html";
} @RequestMapping("/login")
public String loginhtml() {
return "/visitor/login.html";
}
@RequestMapping(value = "/loginUser")
public String loginUser(String username,String password,HttpSession session) {
UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
Subject subject = SecurityUtils.getSubject();
try { logger.info(username);
logger.warn(usernamePasswordToken); //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
//每个Realm都能在必要时对提交的AuthenticationTokens作出反应
//所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法 subject.login(usernamePasswordToken); //完成登录
logger.warn("success");
User user=(User) subject.getPrincipal(); session.setAttribute("user", user);
return "/user/index.html";
} catch(Exception e) {
return "/visitor/login.html";//返回登录页面
} }
@RequestMapping("/logOut")
public String logOut(HttpSession session) {
Subject subject = SecurityUtils.getSubject();
subject.logout();
// session.removeAttribute("user");
return "login";
}
}
6:配置shrio和AuthRealm, matcher等。
package com.li.web;
import com.li.dao.pojo.Module;
import com.li.dao.pojo.Role;
import com.li.dao.pojo.User;
import com.li.service.UserService;
import com.li.service.impl.UserServiceImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.springframework.beans.factory.annotation.Autowired;
import sun.rmi.runtime.Log; import java.util.ArrayList;
import java.util.List;
import java.util.Set; public class AuthRealm extends AuthorizingRealm { Logger logger = LogManager.getLogger(AuthRealm.class);
@Autowired
private UserServiceImpl userService; //认证.登录
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
String username = utoken.getUsername(); logger.warn(username);
User user = userService.findUserByName(username); //使用mybatis从数据库中得到用户
logger.warn(user.getUsername()); 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.getRoles();
if(roles.size()>0) {
for(Role role : roles) {
Set<Module> modules = role.getModules();
if(modules.size()>0) {
for(Module module : modules) {
permissions.add(module.getMname());
}
}
}
}
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);//将权限放入shiro中.
return info;
} }
package com.li.web;//package com.li.web; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; public class CredentialsMatcher extends SimpleCredentialsMatcher { Logger logger = LogManager.getLogger(CredentialsMatcher.class);
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
UsernamePasswordToken utoken=(UsernamePasswordToken) token;
//获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
String inPassword = new String(utoken.getPassword());
logger.warn(inPassword);
//获得数据库中的密码
String dbPassword=(String) info.getCredentials();
logger.warn(dbPassword);
//进行密码的比对
return this.equals(inPassword, dbPassword);
} }
package com.li.web; import com.li.web.CredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; /**
* shiro的配置类
* @author Administrator
*
*/
@Configuration
public class ShiroConfiguration {
@Bean(name="shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
bean.setSecurityManager(manager);
//配置访问权限
LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
filterChainDefinitionMap.put("/loginUser", "anon");
filterChainDefinitionMap.put("/logOut*","logout");
filterChainDefinitionMap.put("/visitor/*", "anon"); //游客资源 filterChainDefinitionMap.put("/**", "authc");//表示需要认证才可以访问
// filterChainDefinitionMap.put("/*.*", "authc");
//配置登录的url和登录成功的url
bean.setLoginUrl("/login"); //校验不通过,就返回/login
bean.setSuccessUrl("/home");
//未授权界面;
bean.setUnauthorizedUrl("/403"); 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;
}
}
8:springboot启动类
package com.li; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan; @EnableAutoConfiguration
@SpringBootApplication
@MapperScan(value = "com.li.dao.Mapper")
public class SpringBootShrioApplication {
public static void main(String[] args){
SpringApplication.run(SpringBootShrioApplication.class, args);
}
}
9:在application.yml中配置springboot
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/shrio
username: root
password: 1367356
devtools:
restart:
enabled: true mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml #Mapper所在的配置文件路径,进行扫描
config-location: classpath:mybatis/mybatis-config.xml # mybaits-config文件
# type-aliases-package: com.liyafei.dao.pojo # pojo所在的包,与表一一对应
10:配置mybatis的xml文件
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
</typeAliases>
</configuration>
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.li.dao.Mapper.UserMapper">
<resultMap type="com.li.dao.pojo.User" id="userMap">
<id property="uid" column="uid"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<collection property="roles" ofType="com.li.dao.pojo.Role">
<id property="rid" column="rid"/>
<result property="rname" column="rname"/>
<collection property="modules" ofType="com.li.dao.pojo.Module">
<id property="mid" column="mid"/>
<result property="mname" column="mname"/>
</collection>
</collection>
</resultMap>
<select id="findByUserName" parameterType="string" resultMap="userMap">
SELECT u.*,r.*,m.* FROM user u inner join user_role ur on ur.uid=u.uid
inner join role r on r.rid=ur.rid
inner join module_role mr on mr.rid=r.rid
inner join module m on mr.mid=m.mid
WHERE username=#{username};
</select>
</mapper>
11:配置log4j2 http://www.cnblogs.com/liyafei/p/8341885.html
12 在resource/static目录下配置静态资源html文件,和 ShiroConfiguration.java中配置的应该对应。
无需注册就能访问的放在visitor目录下,login.html
对应
filterChainDefinitionMap.put("/visitor/*", "anon"); //游客资源
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
<h1>欢迎登录!${user.username }</h1>
<form action="../loginUser" method="get">
<input type="text" name="username"><br>
<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
需要注册才能访问的放到其它目录下,例如user目录下的index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
index.html
</body>
</html>
13:启动spring boot,访问任意非游客资源,例如 http://localhost:8080/loginUser
跳转到登录页面。
输入用户名hlhdidi和密码123 点击提交
验证通过,跳转到index.html
14:系统结构图