下面是一个简单的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 ('1', 'add'); INSERT INTO `module` VALUES ('2', 'delete'); INSERT INTO `module` VALUES ('3', 'query'); INSERT INTO `module` VALUES ('4', '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 ('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 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 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');
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:系统结构图