[java] Shiro 框架学习 (二)Spring Boot 整合
环境
开发工具:IDEA
jdk版本:jdk1.8
创建项目
1.新建spring-boot项目
项目结构:
2.导包 pom.xml文件
添加spring-boot 父级依赖,maven用户可用通过继承parent项目来获得一些合理的默认配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
导入spring-boot快速搭建web项目依赖包和集成shiro框架的依赖包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-Java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.4</version>
</dependency>
</dependencies>
添加spring - boot 支持maven
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.配置application.yml 文件,springboot项目所有配置都在该文件中完成
server:
port: 8082
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
jpa:
show-sql: true
hibernate:
ddl-auto: update
http:
encoding:
charset: utf-8
enabled: true
4.创建用户,角色,权限实体类,shiro权限控制必须有这个三个实体类(表)
User类
package com.ztwow.springshiro.entity;
import javax.persistence.*;
import java.util.List;
/**
* user
* 用户实体类
*
* */
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String name;
private Integer password;
@OneToMany(cascade = CascadeType.ALL,mappedBy = "user")
private List<Role> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public Integer getPassword() {
return password;
}
public void setPassword(Integer password) {
this.password = password;
}
}
Role类
package com.ztwow.springshiro.entity;
import javax.persistence.*;
import java.util.List;
/**
* role
* 角色实体类
*
* */
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleName;
@ManyToOne(fetch = FetchType.EAGER)
private User user;
@OneToMany(cascade = CascadeType.ALL,mappedBy = "role")
private List<Permission> permissions;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Permission> getPermissions() {
return permissions;
}
public void setPermissions(List<Permission> permissions) {
this.permissions = permissions;
}
}
permission类
package com.ztwow.springshiro.entity;
import javax.persistence.*;
/**
* permission
* 权限实体类
*
* */
@Entity
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String permission;
@ManyToOne(fetch = FetchType.EAGER)
private Role role;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
- 持久层接口和实现类
使用JPA操作数据库:jpa学习
#baseDao 接口 继承JPA动态查询和分页
package com.ztwow.springshiro.dao;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.io.Serializable;
@NoRepositoryBean
public interface BaseDao<T,I extends Serializable> extends PagingAndSortingRepository<T,I>, JpaSpecificationExecutor<T> {
}
#User 接口 实现baseDao
package com.ztwow.springshiro.dao;
import com.ztwow.springshiro.entity.User;
public interface UserDao extends BaseDao<User,Long>{
User findByName(String name);
}
#Role 接口实现baseDao
package com.ztwow.springshiro.dao;
import com.ztwow.springshiro.entity.Role;
public interface RoleDao extends BaseDao<Role,Long>{
}
编写业务层接口和实现类
业务层接口
package com.ztwow.springshiro.service;
import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;import java.util.Map;
public interface ILoginService {
User addUser(Map<String,Object> map);
Role addRole(Map<String,Object> map);
User findByName(String name);
}
#实现类
package com.ztwow.springshiro.service.impl;
import com.ztwow.springshiro.dao.RoleDao;
import com.ztwow.springshiro.dao.UserDao;
import com.ztwow.springshiro.entity.Permission;
import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;
import com.ztwow.springshiro.service.ILoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
@Transactional
public class LoginServiceImlp implements ILoginService {
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
//添加用户
@Override
public User addUser(Map<String, Object> map) {
User user = new User();
user.setName(map.get("username").toString());
user.setPassword(Integer.valueOf(map.get("password").toString()));
userDao.save(user);
return user;
}
//添加角色
@Override
public Role addRole(Map<String, Object> map) {
User user = userDao.findOne(Long.valueOf(map.get("userId").toString()));
Role role = new Role();
role.setRoleName(map.get("roleName").toString());
role.setUser(user);
Permission permission1 = new Permission();
permission1.setRole(role);
permission1.setPermission("create");
Permission permission2 =new Permission();
permission2.setPermission("update");
permission2.setRole(role);
List<Permission> permissions = new ArrayList<Permission>();
permissions.add(permission1);permissions.add(permission2);
role.setPermissions(permissions);
roleDao.save(role);
return role;
}
//通过用户名查询用户
@Override
public User findByName(String name){
return userDao.findByName(name);
}
}
7.Shiro自定义配置类,通过@Bean注解的方式代替springMVC的XMl方式配置
package com.ztwow.springshiro.config;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfiguration {
//加入自己的验证方式到容器
@Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工厂,(添加)设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map = new HashMap<String, String>();
//登出
map.put("/logout","logout");
//对所有用户认证
map.put("/**","authc");
//登录
shiroFilterFactoryBean.setLoginUrl("/login");
//首页
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
Realml类 用于获取安全数据,给用户添加角色和权限,认证提交的用户是否合法,并通过用户获取安全数据
package com.ztwow.springshiro.config;
import com.ztwow.springshiro.entity.Permission;
import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;
import com.ztwow.springshiro.service.ILoginService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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;/**
- 实现AuthorizingRealm接口用户用户认证
* - AuthorizingRealm
- 授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,
- 常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限
*/
public class MyShiroRealm extends AuthorizingRealm {
//用于用户查询
@Autowired
private ILoginService loginService;/**
- 角色权限和对应权限添加
* */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String name = (String) principalCollection.getPrimaryPrincipal();
//查询用户名称
User user = loginService.findByName(name);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();for(Role role:user.getRoles()) {
//添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
for (Permission permission : role.getPermissions()) {
//添加权限
simpleAuthorizationInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorizationInfo;
}/*
- 用户认证
* */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if(authenticationToken.getPrincipal() == null){return null;
}
String name = authenticationToken.getPrincipal().toString();
User user = loginService.findByName(name);if(user == null){
//用户不存在返回后会报出异常
return null;
}else{
//这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name,user.getPassword().toString(),getName());
return simpleAuthenticationInfo;
}
}
}
- 角色权限和对应权限添加
- 实现AuthorizingRealm接口用户用户认证
8.Controller类
package com.ztwow.springshiro.controller;
import com.ztwow.springshiro.entity.Role;
import com.ztwow.springshiro.entity.User;
import com.ztwow.springshiro.service.ILoginService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;
@RestController
public class LoginController {
@Resource
private ILoginService loginService;
//退出的时候是get请求,主要是用于退出
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(){
return "login";
}
//post登录
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestBody Map map){
//添加用户认证信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
map.get("username").toString(),
map.get("password").toString());
//进行验证,这里可以捕获异常,然后返回对应信息
subject.login(usernamePasswordToken);
return "login";
}
@RequestMapping(value = "/index")
public String index(){
return "index";
}
//登出
@RequestMapping(value = "/logout")
public String logout(){
return "logout";
}
//错误页面展示
@RequestMapping(value = "/error",method = RequestMethod.POST)
public String error(){
return "error ok!";
}
//数据初始化
@RequestMapping(value = "/addUser")
public String addUser(@RequestBody Map<String,Object> map){
User user = loginService.addUser(map);
return "addUser is ok! \n" + user;
}
//角色初始化
@RequestMapping(value = "/addRole")
public String addRole(@RequestBody Map<String,Object> map){
Role role = loginService.addRole(map);
return "addRole is ok! \n" + role;
}
//注解的使用
@RequiresRoles("admin")
@RequiresPermissions("create")
@RequestMapping(value = "/create")
public String create(){
return "Create success!";
}
}
主要流程:页面所有的操作请求都会通过subject(代表当前用户),然后将subject绑定到SecurityManager上,由SecurityManager管理有所与subject的交互,当SecurityManager需要验证用户身份是否合法,会通过Realm提供的Authentication和Authorization认证用户获取安全数据
还没有评论,来说两句吧...