Spring Boot与Shiro整合案例,用户认证部分。
Spring Boot集成Shiro主要配置两个类: ShiroConfig
类及继承AuthorizingRealm的Realm
类。
- ShiroConfig:是Shiro的配置,相当于Spring中的xml配置。包括:包括过滤器(ShiroFilter)、安全事务管理器(SecurityManager)、密码凭证匹配器(CredentialsMatcher)、缓冲管理器(EhCacheManager)、AOP注解支持(authorizationAttributeSourceAdvisor)、等等
- UserRealm:自定义的UserRealm继承自AuthorizingRealm,重写
doGetAuthorizationInfo
(授权认证)和doGetAuthenticationInfo
(登陆认证)这两个方法。
1. 依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <dependencies> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.4.0</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
|
2. ShiroConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| @Configuration public class ShiroConfig {
@Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/403");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/fonts/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }
@Bean public DefaultWebSecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm()); return securityManager; }
@Bean public UserRealm userRealm(){ UserRealm userRealm = new UserRealm(); return userRealm; } }
|
3. 自定义Realm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| @Slf4j public class UserRealm extends AuthorizingRealm {
@Autowired private UserMapper userMapper;
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) { return null; }
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials());
log.info("用户:{} 执行登录认证操作", userName);
User user = userMapper.findByUserName(userName);
if (user == null) { throw new UnknownAccountException("用户名或密码错误!"); } if (!password.equals(user.getPassword())) { throw new IncorrectCredentialsException("用户名或密码错误!"); }
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName()); return info; } }
|
4. Service/Mapper/SQL
参考工程中的data.sql
5. html
登录界面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登录</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <div class="login-page"> <div class="form"> <input type="text" placeholder="用户名" name="username" required="required"/><br/> <input type="password" placeholder="密码" name="password" required="required"/><br/> <button onclick="login()">登录</button> </div> </div> </body> <script th:inline="javascript"> function login() { var username = $("input[name='username']").val(); var password = $("input[name='password']").val(); $.ajax({ type: "post", url: "/login", data: {"username": username,"password": password}, dataType: "json", success: function (r) { if (r.code == 0) { location.href = '/index'; } else { alert(r.msg); } } }); } </script> </html>
|
首页:
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>首页</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <p>你好![[${user.username}]]</p> <a th:href="@{/logout}">注销</a> </body> </html>
|
参考资料
代码获取
https://github.com/lujiahao0708/LearnSpring
Tips
欢迎收藏和转发,感谢你的支持!(๑•̀ㅂ•́)و✧
欢迎关注我:后端小哥,专注后端开发,希望和你一起进步!