diff --git a/pom.xml b/pom.xml index 228c7a8..d80e490 100644 --- a/pom.xml +++ b/pom.xml @@ -1,111 +1,111 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - top.fjy8018 - shiro - 0.0.1-SNAPSHOT - jar + top.fjy8018 + shiro + 0.0.1-SNAPSHOT + jar - shiro - Demo project for Spring Boot plus Shiro + shiro + Demo project for Spring Boot plus Shiro - - org.springframework.boot - spring-boot-starter-parent - 2.0.3.RELEASE - - + + org.springframework.boot + spring-boot-starter-parent + 2.0.3.RELEASE + + - - UTF-8 - UTF-8 - 1.8 - + + UTF-8 + UTF-8 + 1.8 + - - - org.springframework.boot - spring-boot-starter-web - - - org.mybatis.spring.boot - mybatis-spring-boot-starter - 1.3.2 - + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + - - mysql - mysql-connector-java - - - - org.apache.shiro - shiro-core - 1.4.0 - - - - org.apache.shiro - shiro-spring - 1.4.0 - - - - com.alibaba - druid - 1.1.10 - - - - org.apache.commons - commons-lang3 - 3.7 - - - - org.springframework - spring-context-support - - - - org.apache.tomcat - tomcat-jasper - 9.0.10 - - - - javax.servlet - javax.servlet-api - + + mysql + mysql-connector-java + + + + org.apache.shiro + shiro-core + 1.4.0 + + + + org.apache.shiro + shiro-spring + 1.4.0 + + + + com.alibaba + druid + 1.1.10 + + + + org.apache.commons + commons-lang3 + 3.7 + + + + org.springframework + spring-context-support + + + + org.apache.tomcat + tomcat-jasper + 9.0.10 + + + + javax.servlet + javax.servlet-api + javax.servlet jstl - - org.projectlombok - lombok - true - + + org.projectlombok + lombok + true + - - org.springframework.boot - spring-boot-starter-test - test - - + + org.springframework.boot + spring-boot-starter-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + diff --git a/sql.sql b/sql.sql index 76156f9..7fa90bb 100644 --- a/sql.sql +++ b/sql.sql @@ -1,30 +1,39 @@ DROP DATABASE db_shiroTest; -GRANT ALL ON db_shiroTest.* TO trs@localhost IDENTIFIED BY 'shiro'; -flush privileges; -CREATE DATABASE IF NOT EXISTS db_shiroTest DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; +GRANT ALL ON db_shiroTest.* TO trs@localhost +IDENTIFIED BY 'shiro'; +FLUSH PRIVILEGES; +CREATE DATABASE IF NOT EXISTS db_shiroTest + DEFAULT CHARSET utf8mb4 + COLLATE utf8mb4_general_ci; USE db_shiroTest; -- 权限表 -- CREATE TABLE permission ( - pid INT(11) NOT NULL AUTO_INCREMENT, + pid INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL DEFAULT '', - url VARCHAR(255) DEFAULT '', + url VARCHAR(255) DEFAULT '', PRIMARY KEY (pid) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; -- 用户表 -- CREATE TABLE user ( - uid INT(11) NOT NULL AUTO_INCREMENT, + uid INT(11) NOT NULL AUTO_INCREMENT, username VARCHAR(255) NOT NULL DEFAULT '', password VARCHAR(255) NOT NULL DEFAULT '', PRIMARY KEY (uid) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; -- 角色表 -- CREATE TABLE role ( - rid INT(11) NOT NULL AUTO_INCREMENT, + rid INT(11) NOT NULL AUTO_INCREMENT, rname VARCHAR(255) NOT NULL DEFAULT '', PRIMARY KEY (rid) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; -- 权限角色关系表 -- CREATE TABLE permission_role ( @@ -32,7 +41,9 @@ CREATE TABLE permission_role ( pid INT(11) NOT NULL, CONSTRAINT FK_prid FOREIGN KEY (rid) REFERENCES role (rid), CONSTRAINT FK_pid FOREIGN KEY (pid) REFERENCES permission (pid) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; -- 用户角色关系表 -- CREATE TABLE user_role ( @@ -40,38 +51,43 @@ CREATE TABLE user_role ( uid INT(11) NOT NULL, CONSTRAINT FK_urid FOREIGN KEY (rid) REFERENCES role (rid), CONSTRAINT FK_uid FOREIGN KEY (uid) REFERENCES user (uid) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; -- 初始化数据 -- -INSERT INTO permission (pid,name, url) VALUE ('1','add',''); -INSERT INTO permission (pid,name, url) VALUE ('2','delete',''); -INSERT INTO permission (pid,name, url) VALUE ('3','edit',''); -INSERT INTO permission (pid,name, url) VALUE ('4','query',''); +INSERT INTO permission (pid, name, url) VALUE ('1', 'add', ''); +INSERT INTO permission (pid, name, url) VALUE ('2', 'delete', ''); +INSERT INTO permission (pid, name, url) VALUE ('3', 'edit', ''); +INSERT INTO permission (pid, name, url) VALUE ('4', 'query', ''); -INSERT INTO user (uid,username, password) VALUE ('1','admin','0000'); -INSERT INTO user (uid,username, password) VALUE ('2','trs','trs'); +INSERT INTO user (uid, username, password) VALUE ('1', 'admin', '0000'); +INSERT INTO user (uid, username, password) VALUE ('2', 'trs', 'trs'); -INSERT INTO role (rid,rname) VALUE ('1','admin'); -INSERT INTO role (rid,rname) VALUE ('2','customer'); -INSERT INTO role (rid,rname) VALUE ('3','guest'); +INSERT INTO role (rid, rname) VALUE ('1', 'admin'); +INSERT INTO role (rid, rname) VALUE ('2', 'customer'); +INSERT INTO role (rid, rname) VALUE ('3', 'guest'); -INSERT INTO permission_role (rid, pid) VALUE ('1','1'); -INSERT INTO permission_role (rid, pid) VALUE ('1','2'); -INSERT INTO permission_role (rid, pid) VALUE ('1','3'); -INSERT INTO permission_role (rid, pid) VALUE ('1','4'); +INSERT INTO permission_role (rid, pid) VALUE ('1', '1'); +INSERT INTO permission_role (rid, pid) VALUE ('1', '2'); +INSERT INTO permission_role (rid, pid) VALUE ('1', '3'); +INSERT INTO permission_role (rid, pid) VALUE ('1', '4'); -INSERT INTO permission_role (rid, pid) VALUE ('2','1'); -INSERT INTO permission_role (rid, pid) VALUE ('1','3'); -INSERT INTO permission_role (rid, pid) VALUE ('1','4'); -INSERT INTO permission_role (rid, pid) VALUE ('3','4'); +INSERT INTO permission_role (rid, pid) VALUE ('2', '1'); +INSERT INTO permission_role (rid, pid) VALUE ('1', '3'); +INSERT INTO permission_role (rid, pid) VALUE ('1', '4'); +INSERT INTO permission_role (rid, pid) VALUE ('3', '4'); -INSERT INTO user_role (rid, uid) VALUE ('1','1'); -INSERT INTO user_role (rid, uid) VALUE ('2','2'); +INSERT INTO user_role (rid, uid) VALUE ('1', '1'); +INSERT INTO user_role (rid, uid) VALUE ('2', '2'); -SELECT u.*,r.*,p.* - FROM user u - INNER JOIN user_role ur ON ur.uid = u.uid - INNER JOIN role r ON ur.uid = r.rid - INNER JOIN permission_role pr ON r.rid = pr.rid - INNER JOIN permission p ON pr.pid = p.pid - WHERE u.username +SELECT + u.*, + r.*, + p.* +FROM user u + INNER JOIN user_role ur ON ur.uid = u.uid + INNER JOIN role r ON ur.uid = r.rid + INNER JOIN permission_role pr ON r.rid = pr.rid + INNER JOIN permission p ON pr.pid = p.pid +WHERE u.username diff --git a/src/main/java/top/fjy8018/shiro/ShiroApplication.java b/src/main/java/top/fjy8018/shiro/ShiroApplication.java index 9cad50e..4928b13 100644 --- a/src/main/java/top/fjy8018/shiro/ShiroApplication.java +++ b/src/main/java/top/fjy8018/shiro/ShiroApplication.java @@ -10,7 +10,7 @@ import org.springframework.context.annotation.ComponentScan; @MapperScan(basePackages = {"top.fjy8018.shiro.mapper"}) public class ShiroApplication { - public static void main(String[] args) { - SpringApplication.run(ShiroApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(ShiroApplication.class, args); + } } diff --git a/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java b/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java index ae2b867..cfa7160 100644 --- a/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java +++ b/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java @@ -15,6 +15,7 @@ import java.util.LinkedHashMap; /** * shiro核心配置 + * * @author F嘉阳 * @date 2018/7/6 10:29 */ @@ -22,7 +23,7 @@ import java.util.LinkedHashMap; public class ShiroConfiguration { @Bean("shiroFilter") - public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager){ + public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(manager); @@ -32,11 +33,18 @@ public class ShiroConfiguration { bean.setUnauthorizedUrl("/unauthorized"); // 配置拦截 - LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>(); + LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>(); // 主页设置拦截,第二个参数的含义在org.apache.shiro.web.filter.mgt.DefaultFilter的枚举类中,authc为表单验证 - filterChainDefinitionMap.put("/index","authc"); + filterChainDefinitionMap.put("/index", "authc"); // 登录页无需拦截,anon即匿名访问 - filterChainDefinitionMap.put("/login","anon"); + filterChainDefinitionMap.put("/login", "anon"); + filterChainDefinitionMap.put("/doLogin","anon"); + + // 指定页面只能给指定用户访问,校验角色名称类org.apache.shiro.web.filter.authz.RolesAuthorizationFilter + filterChainDefinitionMap.put("/admin","roles[admin]"); + + // 用户登录后可以访问所有接口 + filterChainDefinitionMap.put("/**", "user"); bean.setFilterChainDefinitionMap(filterChainDefinitionMap); @@ -45,7 +53,7 @@ public class ShiroConfiguration { @Bean("securityManager") - public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm){ + public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) { DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(authRealm); return manager; @@ -54,11 +62,12 @@ public class ShiroConfiguration { /** * 自定义的Realm + * * @param matcher * @return */ @Bean("authRealm") - public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher){ + public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) { AuthRealm authRealm = new AuthRealm(); authRealm.setCredentialsMatcher(matcher); return authRealm; @@ -66,20 +75,22 @@ public class ShiroConfiguration { /** * 自定义密码校验规则 + * * @return */ @Bean("credentialsMatcher") - public CredentialsMatcher credentialsMatcher(){ + public CredentialsMatcher credentialsMatcher() { return new CredentialsMatcher(); } /** * 配置spring与shiro关联,指定spring使用的SecurityManager为自定义的SecurityManager + * * @param securityManager * @return */ @Bean - public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){ + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); @@ -88,10 +99,11 @@ public class ShiroConfiguration { /** * 代理所有servlet的过滤器链 + * * @return */ @Bean - public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){ + public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); diff --git a/src/main/java/top/fjy8018/shiro/controller/LoginController.java b/src/main/java/top/fjy8018/shiro/controller/LoginController.java index 5f1271c..1ffd254 100644 --- a/src/main/java/top/fjy8018/shiro/controller/LoginController.java +++ b/src/main/java/top/fjy8018/shiro/controller/LoginController.java @@ -19,25 +19,34 @@ import javax.servlet.http.HttpSession; public class LoginController { @RequestMapping("/login") - public String login(){ + public String login() { return "login"; } @RequestMapping("/doLogin") - public String doLogin(LoginForm form, HttpSession session){ - UsernamePasswordToken token = new UsernamePasswordToken(form.getUsername(),form.getPassword()); + public String doLogin(LoginForm form, HttpSession session) { + UsernamePasswordToken token = new UsernamePasswordToken(form.getUsername(), form.getPassword()); Subject subject = SecurityUtils.getSubject(); - try{ + try { subject.login(token); // 若未发生异常则此处获得用户 User user = (User) subject.getPrincipal(); // 将用户写入session - session.setAttribute(GlobalConstant.USER_SESSION_KEY,user); + session.setAttribute(GlobalConstant.USER_SESSION_KEY, user); return "index"; - }catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); return "login"; } } + + @RequestMapping("/logout") + public String logout() { + Subject subject = SecurityUtils.getSubject(); + if (subject != null) { + subject.logout(); + } + return "login"; + } } diff --git a/src/main/java/top/fjy8018/shiro/controller/NavController.java b/src/main/java/top/fjy8018/shiro/controller/NavController.java index f8d260e..66b1f2c 100644 --- a/src/main/java/top/fjy8018/shiro/controller/NavController.java +++ b/src/main/java/top/fjy8018/shiro/controller/NavController.java @@ -2,9 +2,11 @@ package top.fjy8018.shiro.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; /** * 页面导航 + * * @author F嘉阳 * @date 2018/7/6 10:57 */ @@ -12,7 +14,14 @@ import org.springframework.web.bind.annotation.RequestMapping; public class NavController { @RequestMapping("/index") - public String index(){ + public String index() { return "index"; } + + @RequestMapping("/admin") + @ResponseBody + public String admin() { + return "admin success"; + } + } diff --git a/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java b/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java index a4aa926..acd24aa 100644 --- a/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java +++ b/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java @@ -7,6 +7,7 @@ import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; /** * 自定义校验规则 + * * @author F嘉阳 * @date 2018/7/6 10:25 */ @@ -15,9 +16,9 @@ public class CredentialsMatcher extends SimpleCredentialsMatcher { @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; - String password = new String (usernamePasswordToken.getPassword()); + String password = new String(usernamePasswordToken.getPassword()); String dbPassword = (String) info.getCredentials(); // 数据库密码与用户密码匹配 - return this.equals(password,dbPassword); + return this.equals(password, dbPassword); } } diff --git a/src/main/java/top/fjy8018/shiro/form/LoginForm.java b/src/main/java/top/fjy8018/shiro/form/LoginForm.java index f0b7dab..950ce52 100644 --- a/src/main/java/top/fjy8018/shiro/form/LoginForm.java +++ b/src/main/java/top/fjy8018/shiro/form/LoginForm.java @@ -4,6 +4,7 @@ import lombok.Data; /** * 登录表单 + * * @author F嘉阳 * @date 2018/7/6 10:59 */ diff --git a/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java b/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java index 7217f91..de3466d 100644 --- a/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java +++ b/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java @@ -27,6 +27,7 @@ public class AuthRealm extends AuthorizingRealm { /** * shiro登录成功后的授权方法 + * * @param principalCollection * @return */ @@ -36,14 +37,16 @@ public class AuthRealm extends AuthorizingRealm { User user = (User) principalCollection.fromRealm(this.getClass().getName()).iterator().next(); List permissionList = new ArrayList<>(); + List roleList = new ArrayList<>(); Set roleSet = user.getRoles(); // 取角色 - if (CollectionUtils.isNotEmpty(roleSet)){ - for (Role role : roleSet){ + if (CollectionUtils.isNotEmpty(roleSet)) { + for (Role role : roleSet) { + roleList.add(role.getRname()); // 取权限 Set permissionSet = role.getPermissions(); - if (CollectionUtils.isNotEmpty(permissionSet)){ - for (Permission permission : permissionSet){ + if (CollectionUtils.isNotEmpty(permissionSet)) { + for (Permission permission : permissionSet) { permissionList.add(permission.getName()); } } @@ -52,12 +55,14 @@ public class AuthRealm extends AuthorizingRealm { } SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermissions(permissionList); + info.addRoles(roleList); return info; } /** * 认证登录 + * * @param authenticationToken * @return * @throws AuthenticationException @@ -69,6 +74,6 @@ public class AuthRealm extends AuthorizingRealm { String username = usernamePasswordToken.getUsername(); // 通过用户名查用户是否存在,合法则登录认证通过 User user = userService.findByUsername(username); - return new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getName()); + return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName()); } } diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml index de3bd41..87f6087 100644 --- a/src/main/resources/mapper/UserMapper.xml +++ b/src/main/resources/mapper/UserMapper.xml @@ -2,28 +2,28 @@ - + - - + + - - + + - - - + + + \ No newline at end of file diff --git a/src/test/java/top/fjy8018/shiro/ShiroApplicationTests.java b/src/test/java/top/fjy8018/shiro/ShiroApplicationTests.java index ab2e7eb..0083beb 100644 --- a/src/test/java/top/fjy8018/shiro/ShiroApplicationTests.java +++ b/src/test/java/top/fjy8018/shiro/ShiroApplicationTests.java @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest public class ShiroApplicationTests { - @Test - public void contextLoads() { - } + @Test + public void contextLoads() { + } }