认证
两个shiro配置类
UserRealm
public class UserRealm extends AuthorizingRealm { @Autowired UserService userService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("执行了=>授权doGetAuthorizationInfo"); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了=>认证doGetAuthorizationInfo"); //连接真实数据库 UsernamePasswordToken userToken=(UsernamePasswordToken)token;//取出前端form表单提交的 User user = userService.queryByName(userToken.getUsername());//用前端提交的username对数据库做查询. if (user==null){ return null;//抛出异常,对异常的处理在MyController中做MyController下面有 } //密码认证shiro做 //获取认证的用户 Subject subject= SecurityUtils.getSubject(); //封装用户的登陆数据 return new SimpleAuthenticationInfo("",user.getPwd(),""); } }
ShiroConfig
@configration
public class ShiroConfig{
//创建realm对象 ,需要自定义类:1 @Bean(name="userRealm") public UserRealm userRealm(){ return new UserRealm(); }
//defaultWebSecurityManager @Bean(name="DWSM") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); //关联UserRealm manager.setRealm(userRealm); return manager; }
@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("DWSM")DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //shiro内置过滤器 /* * anon无需认证就可以访问 * authc:必须认证了才能访问 * user:必须有记住我,才可以访问 * perms 拥有对某个资源的权限才能访问 * role: 拥有某个角色权限才能访问 * * */ LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("/user/add","authc"); linkedHashMap.put("/user/update","authc"); bean.setFilterChainDefinitionMap(linkedHashMap); bean.setLoginUrl("/tologin"); return bean; }
}
MyController
@Controller public class MyController {
@RequestMapping("/login") public String login(String username,String password,Model model){ Subject subject= SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); return "index"; }catch (UnknownAccountException e){ model.addAttribute("msg","用户名错误"); return "login"; }catch (IncorrectCredentialsException e){ model.addAttribute("msg","密码错误"); return "login"; } }
@RequestMapping({"/","/index"}) public String index(Model model){ model.addAttribute("msg","hello,Shiro"); return "index"; } @RequestMapping("/user/add") public String add(){ return "user/add"; } @RequestMapping("/user/update") public String update(){ return "user/update"; } @RequestMapping("/tologin") public String tologin(){ return "login"; } }
加入授权
数据库中加入了新字段perms用来规定角色具有的身份
1 刘明 123456 null
2 飞飞 123456 user:add
3 火华 123465 user:update
ShiroConfig UserRealm Mycontroller分别如下:
{
@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("DWSM")DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //shiro内置过滤器 /* * anon无需认证就可以访问 * authc:必须认证了才能访问 * user:必须有记住我,才可以访问 * perms 拥有对某个资源的权限才能访问 * role: 拥有某个角色权限才能访问 * * */ //拦截 LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>(); //授权 linkedHashMap.put("/user/add","perms[user:add]"); linkedHashMap.put("/user/update","perms[user:update]"); linkedHashMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(linkedHashMap); //设置登陆的请求 bean.setLoginUrl("/tologin"); //未经授权的页面 bean.setUnauthorizedUrl("/noauth"); return bean; } //defaultWebSecurityManager @Bean(name="DWSM") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); //关联UserRealm manager.setRealm(userRealm); return manager; } //创建realm对象 ,需要自定义类:1 @Bean(name="userRealm") public UserRealm userRealm(){ return new UserRealm(); }
}
package com.bootshiro.config; import com.bootshiro.pojo.User; import com.bootshiro.service.UserService; import org.apache.shiro.SecurityUtils; 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.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; public class UserRealm extends AuthorizingRealm { @Autowired UserService userService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("执行了=>授权doGetAuthorizationInfo"); //授权 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //info.addStringPermission("user:add"); //拿到当前登陆的这个对象 Subject subject = SecurityUtils.getSubject(); User principal = (User) subject.getPrincipal(); //设置当前用户的权限 info.addStringPermission(principal.getPerms()); return info; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了=>认证doGetAuthorizationInfo"); //连接真实数据库 UsernamePasswordToken userToken=(UsernamePasswordToken)token; User user = userService.queryByName(userToken.getUsername()); if (user==null){ return null;//抛出异常 } //密码认证shiro做 //获取认证的用户 Subject subject= SecurityUtils.getSubject(); //封装用户的登陆数据 return new SimpleAuthenticationInfo(user,user.getPwd(),""); } }
controller新增
@RequestMapping("/noauth") @ResponseBody public String unauthorized(){ return "未经授权无法访问此页面"; }
几个页面
index.xml
<h1>首页</h1> <p th:text="${msg}"></p> <a th:href="@{/user/update}">update</a> <br> <a th:href="@{/user/add}">add</a>
login.html
<p th:text="${msg}"></p> <form th:action="@{/login}"> <p>用户名:</p><input type="text" name="username"><br> <p>密 码:</p><input type="password" name="password"><br> <input type="submit"> </form>
user文件夹下两个html
add.html
<h1>add</h1>
update.html
<h1>update<h1>
pom.xml
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--6--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
application.yml
spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/ha?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver profiles:这里是把日志搞里头 没用 include: log4j mybatis-plus: type-aliases-package: com.bootshiro.pojo mapper-locations: classpath:mapper/*.xml
application-log4j.properties可以不要做日志
### set log levels ### log4j.rootLogger = DEBUG , C , D , E ### console ### log4j.appender.C = org.apache.log4j.ConsoleAppender log4j.appender.C.Target = System.out log4j.appender.C.layout = org.apache.log4j.PatternLayout log4j.appender.C.layout.ConversionPattern = [mybatis_study][%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n ### log file ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = ../logs/mybatis_study.log log4j.appender.D.Append = true log4j.appender.D.Threshold = INFO log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = [mybatis_study][%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n ### exception ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File = ../logs/mybatis_study_error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = [mybatis_study][%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n ###mybatis show sql### log4j.logger.com.ibatis=debug log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug log4j.logger.java.sql.Connection=debug log4j.logger.java.sql.Statement=debug log4j.logger.java.sql.PreparedStatement=debug
实体
User
@Data @NoArgsConstructor @AllArgsConstructor public class User { private int id; private String name; private String pwd; }
mapper 和 mapper.xml
@Mapper @Repository public interface UserMapper extends BaseMapper<User> { List<User> query(); User queryByName(String name); }
<?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.bootshiro.mapper.UserMapper"> <select id="query" resultType="com.bootshiro.pojo.User"> select * from ha.user </select> <select id="queryByName" resultType="com.bootshiro.pojo.User"> select * from ha.user where name=#{name} </select> </mapper>
service 和 serviceImpl
public interface UserService { List<User> query(); User queryByName(String name); }
@Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Override public List<User> query() { return userMapper.query(); } @Override public User queryByName(String name) { return userMapper.queryByName(name); } }