最近在学习shiro,今天做一个总结
shiro简单介绍
Shiro是Apache下的一个开源项目,我们称之为Apache Shiro。它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与 Spring Security 一样都是做一个权限的安全框架,但是与Spring Security 相比,在于 Shiro 使用了比较简单易懂易于使用的授权方式。
Apache Shiro的三大核心组件
Subject 当前用户的操作
SecurityManager 用于管理所有的Subject
Realms 用于进行权限信息的验证,也是我们需要自己实现的
首先我们先进行maven依赖的添加
<dependency>//添加log日志
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>//添加thymeleaf和springboot整合后的依赖
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>//添加shiro和springboot整合的依赖
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.0version>
dependency>
<dependency>//添加thymeleaf和shiro整合的依赖
<groupId>com.github.theborakompanionigroupId>
<artifactId>thymeleaf-extras-shiroartifactId>
<version>1.2.1version>
dependency>
<dependency>//mysql的依赖
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>6.0.6version>
dependency>
<dependency>//添加log4j的依赖
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4jartifactId>
<version>1.3.8.RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>//mybatis和springboot的整合
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.3.0version>
dependency>
<dependency>
<groupId>net.sourceforge.nekohtmlgroupId>
<artifactId>nekohtmlartifactId>
<version>1.9.22version>
dependency>
yml中的配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_shiro?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
username: root
password: "000000"
thymeleaf:
mode: LEGACYHTML5
mybatis:
type-aliases-package: com.example.shiro.domain
mapper-locations: classpath:mapper/*Mapper.xml
configuration:
map-underscore-to-camel-case: true
use-generated-keys: true
thymeleaf的配置
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
开发时关闭缓存,不然没法看到实时页面
spring.thymeleaf.cache=false
启动类上添加扫描的mapper
@SpringBootApplication
@MapperScan("com.example.shiro.mapper")
public class ShiroApplication {
public static void main(String[] args) {
SpringApplication.run(ShiroApplication.class, args);
}
}
shiro文件的配置
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login.html");//登录时跳转的页面
shiroFilterFactoryBean.setSuccessUrl("/success");//认证成功后跳转的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/403.jsp");//未授权后跳转的页面
Map filterChainDefinitionMap=new LinkedHashMap();
filterChainDefinitionMap.put("/login1","anon");//anon,无需认证
filterChainDefinitionMap.put("/login","anon");
filterChainDefinitionMap.put("/","authc");//authc,需要认证
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
System.out.println("Shiro拦截器配置成功");
return shiroFilterFactoryBean;
}
@Bean //securityManager的配置
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
@Bean
public MyRealm myShiroRealm(){
return new MyRealm();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
Controller中进行用户密码的认证
@Controller
public class UserController {
private String encoding = "UTF-8";
@PostMapping("/login1")
public String login(HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding(encoding);
String username = request.getParameter("username");
String password = request.getParameter("password");
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.login(token);
return "success";
} catch (Exception e) {
request.setAttribute("user", username);
request.setAttribute("errorMsg", "用户名或密码错误");
return "login";
}
}
}
自定义realm
public class MyRealm extends AuthorizingRealm{
@Autowired
private UserServiceImpl userService;
/***
*
*为当前登录的角色授予角色和权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username= (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authenticationInfo= new SimpleAuthorizationInfo();
authenticationInfo.setStringPermissions(userService.getPermissionByUserName(username));
authenticationInfo.setRoles(userService.getRolesByUserName(username));
return null;
}
/**
* 验证当前登录的用户
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username= (String) authenticationToken.getPrincipal();
User user=userService.getUserByUsername(username);
if (user!=null){
return new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx");
}else{
return null;
}
}
}