springboot 整合 shiro (使用了 thymeleaf模板引擎)
2021-01-15 03:11
YPE html>
标签:hash har out logo list and can esc md5
数据库结构
1. 项目目录结构
2. pom.xml 添加依赖
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot spring-boot-starter-parent2.2.2.RELEASE cn.xej springboot-shiro0.0.1-SNAPSHOT springboot-shiro Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-weborg.mybatis.spring.boot mybatis-spring-boot-starter2.1.2 mysql mysql-connector-javaorg.apache.shiro shiro-spring1.4.1 com.github.theborakompanioni thymeleaf-extras-shiro2.0.0 org.springframework.boot spring-boot-starter-thymeleaforg.springframework.boot spring-boot-devtoolsruntime true com.alibaba druid1.1.13 org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest org.junit.vintage junit-vintage-engineorg.springframework.boot spring-boot-maven-plugin
3. application.yml 配置文件
spring: datasource: url: jdbc:mysql://localhost:3306/tb_shiro?useUnicode=true&&characterEncoding=utf-8&serverTimezone=GMT username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource thymeleaf: cache: false mybatis: mapper-locations: classpath:mapping/*.xml type-aliases-package: cn.xej.pojo configuration: map-underscore-to-camel-case: true # 该配置就是将带有下划线的表字段映射为驼峰格式的实体类属性
4. User 实体类
package cn.xej.pojo; import lombok.Data; @Data public class User { private String userId; private String password; private String name; }
5. UserDao接口
package cn.xej.mapper; import cn.xej.pojo.User; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface UserDao { public User findByUserId(String userId); public ListqueryRolesIdByUserId(String userId); }
6. UserDao.xml文件
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
7. UserService接口
package cn.xej.service; import cn.xej.pojo.User; import java.util.List; public interface UserService { // 根据用户id查询该用户 public User findByUserId(String userId); // 根据用户id获取该用户角色 public ListgetRolesIdByUserId(String userId); }
8. UserServiceimpl接口实现类
package cn.xej.service.impl; import cn.xej.mapper.UserDao; import cn.xej.pojo.User; import cn.xej.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceimpl implements UserService { @Autowired private UserDao userDao; @Override public User findByUserId(String userId) { return userDao.findByUserId(userId); } @Override public ListgetRolesIdByUserId(String userId) { return userDao.queryRolesIdByUserId(userId); } }
9. SpringbootShiroApplication 启动类添加包扫描注解
package cn.xej; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("cn.xej.mapper") // 配置一个或多个包路径,自动的扫描这些包路径下的类,自动的为它们生成代理类。 public class SpringbootShiroApplication { public static void main(String[] args) { SpringApplication.run(SpringbootShiroApplication.class, args); } }
10. RespObj
package cn.xej.common; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class RespObj { private Integer code; private String message; private Object data; public static RespObj build(Integer code,String message,Object data){ return new RespObj(code,message,data); } }
11. SysController(路由跳转控制器)
package cn.xej.controller; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class SysController { // 进入到登录页面 @RequestMapping({"/","/welcome"}) public String welcome(){ return "login"; } // 进入到首页(登录成功或游客) @RequestMapping("/index") public String index(){ return "index"; } }
12. UserController(控制器)
package cn.xej.controller; import cn.xej.common.RespObj; import cn.xej.pojo.User; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpSession; @Controller @RequestMapping("/user") public class UserController { // 登录用户, 返回json数据,因此要加 @ResponseBody注解 @PostMapping("/toLogin") @ResponseBody public RespObj toLogin(String userId, String password, HttpSession session){ // 1. 获取 主体 subject Subject subject = SecurityUtils.getSubject();
// 2. 将账号和密码进行封装 UsernamePasswordToken token = new UsernamePasswordToken(userId,password); // 3. shiro认证,进入自定义UserRealm中 try { subject.login(token);
// 认证成功,将用户名存到session中,返回json数据 session.setAttribute("currentUserName",((User)subject.getPrincipal()).getName()); return RespObj.build(200,"ok",null); } catch (Exception e) { System.out.println("账号或密码错误"); return RespObj.build(500,"账号或密码错误",null); } }
// 注销用户 @PostMapping("/logout") @ResponseBody public RespObj logout(){ Subject subject = SecurityUtils.getSubject(); subject.logout(); return RespObj.build(200,"ok",null); } @RequestMapping("/add") public String add(){ return "pages/add"; } @RequestMapping("/update") public String update(){ return "pages/update"; } }
13. 自定义UserRealm
package cn.xej.config; import cn.xej.pojo.User; import cn.xej.service.UserService; 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 java.util.List; public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("授权"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); User user = (User) principalCollection.getPrimaryPrincipal(); Listroles = userService.getRolesIdByUserId(user.getUserId()); info.addRoles(roles); return info; } // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("认证"); UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; User user = userService.findByUserId(token.getUsername()); if(user==null){ return null; } return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
// 第一个参数,将会传到授权中进行获取,比如 User user = (User) principalCollection.getPrimaryPrincipal();
// 第二个参数,是该用户数据库里的密码 // 第三个参数,是当前类名 } }
14. Shiro配置文件(ShiroConfig)
package cn.xej.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import org.apache.shiro.mgt.SecurityManager; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration // 该注解表示该类是 配置类 public class ShiroConfig { // 我的所有方法名都是类名的首字母小写,不然要写成 @Bean(name="xxx") xxx是自定义的方法名 // 配置自定义Realm @Bean public UserRealm userRealm(){ return new UserRealm(); } // 配置安全管理器,把自定义的Realm添加到安全管理器中 @Bean public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm){ DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(userRealm); return defaultWebSecurityManager; } // 配置Filter工厂,设置对应的过滤条件和跳转条件,把安全管理器添加到Filter工厂中 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); shiroFilterFactoryBean.setLoginUrl("/welcome"); //设置进入登录页面的url shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
shiroFilterFactoryBean.setSuccessUrl("/index"); //设置登录成功url
Mapmap = new LinkedHashMap ();
// index和 user/toLogin两个路径不用拦截 map.put("/index","anon"); map.put("/user/toLogin","anon"); map.put("/**","authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); // 强制使用cglib,防止重复代理和可能引起代理出错的问题 defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } @Bean public ShiroDialect shiroDialect(){ return new ShiroDialect(); } }
15. login.html页面
Title
16. index.html (首页) (当用户没登录时,三元表达式显示游客名字,登录时显示该用户名字,并通过shiro标签执行UserRealm中的授权方法,然后通过该用户的id获取他的角色)
17. 实现用户密码加密
1. 首先在shiro 配置文件中 添加解密规则,如下面的解密凭证器,然后放到UserRealm中
// shiro 解密凭证器 @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("MD5"); hashedCredentialsMatcher.setHashIterations(1024); return hashedCredentialsMatcher; } // 配置自定义Realm @Bean public UserRealm userRealm(HashedCredentialsMatcher hashedCredentialsMatcher){ UserRealm userRealm = new UserRealm(); userRealm.setCredentialsMatcher(hashedCredentialsMatcher); return userRealm; }
2.然后在UserRealm 认证方法中,返回4个参数
// 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("认证"); UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; User user = userService.findByUserId(token.getUsername()); if(user==null){ return null; } return new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getUserId()),getName()); // 第一个参数,将会传到授权中进行获取,比如 User user = (User) principalCollection.getPrimaryPrincipal(); // 第二个参数,是该用户数据库里的密码
// 第三个参数,是salt,这里我是用用户id当作盐
// 第四个参数,是当前类名
}
3. 最后写个测试方法,产生密码加密
“123” 是用户密码
“teacher1” 是加密的盐
1024 是加密次数
String password1 = new SimpleHash("MD5","123","teacher1",1024).toString(); System.out.println("password1 "+password1);
springboot 整合 shiro (使用了 thymeleaf模板引擎)
标签:hash har out logo list and can esc md5
原文地址:https://www.cnblogs.com/Alida/p/12926117.html
文章标题:springboot 整合 shiro (使用了 thymeleaf模板引擎)
文章链接:http://soscw.com/index.php/essay/42061.html