SSH综合项目实战(快递) -- day11 shiro权限控制、后台用户登录

一、常见的权限控制方式

1、url拦截权限控制:基于过滤器实现的拦截


2、方法注解权限控制:基于代理实现的拦截


二、项目中导入权限模块相关实体


1、菜单

package com.itheima.bos.domain.system;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * @description:菜单
 */
@Entity
@Table(name = "T_MENU")
public class Menu {
	@Id
	@GeneratedValue
	@Column(name = "C_ID")
	private int id;
	@Column(name = "C_NAME")
	private String name; // 菜单名称
	@Column(name = "C_PAGE")
	private String page; // 访问路径
	@Column(name = "C_PRIORITY")
	private Integer priority; // 优先级
	@Column(name = "C_DESCRIPTION")
	private String description; // 描述

	@ManyToMany(mappedBy = "menus")
	private Set<Role> roles = new HashSet<Role>(0);

	@OneToMany(mappedBy = "parentMenu")
	private Set<Menu> childrenMenus = new HashSet<Menu>();

	@ManyToOne
	@JoinColumn(name = "C_PID")
	private Menu parentMenu;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPage() {
		return page;
	}

	public void setPage(String page) {
		this.page = page;
	}

	public Integer getPriority() {
		return priority;
	}

	public void setPriority(Integer priority) {
		this.priority = priority;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	public Set<Menu> getChildrenMenus() {
		return childrenMenus;
	}

	public void setChildrenMenus(Set<Menu> childrenMenus) {
		this.childrenMenus = childrenMenus;
	}

	public Menu getParentMenu() {
		return parentMenu;
	}

	public void setParentMenu(Menu parentMenu) {
		this.parentMenu = parentMenu;
	}

}

2、权限

package com.itheima.bos.domain.system;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * @description:权限名称
 */
@Entity
@Table(name = "T_PERMISSION")
public class Permission {

	@Id
	@GeneratedValue
	@Column(name = "C_ID")
	private int id;
	@Column(name = "C_NAME")
	private String name; // 权限名称
	@Column(name = "C_KEYWORD")
	private String keyword; // 权限关键字,用于权限控制
	@Column(name = "C_DESCRIPTION")
	private String description; // 描述

	@ManyToMany(mappedBy = "permissions")
	private Set<Role> roles = new HashSet<Role>(0);

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getKeyword() {
		return keyword;
	}

	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}

	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

}

3、角色

package com.itheima.bos.domain.system;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * @description:角色
 */
@Entity
@Table(name = "T_ROLE")
public class Role {
	@Id
	@GeneratedValue
	@Column(name = "C_ID")
	private int id;
	@Column(name = "C_NAME")
	private String name; // 角色名称
	@Column(name = "C_KEYWORD")
	private String keyword; // 角色关键字,用于权限控制
	@Column(name = "C_DESCRIPTION")
	private String description; // 描述

	@ManyToMany(mappedBy = "roles")
	private Set<User> users = new HashSet<User>(0);

	@ManyToMany
	@JoinTable(name = "T_ROLE_PERMISSION", joinColumns = {
			@JoinColumn(name = "C_ROLE_ID", referencedColumnName = "C_ID") }, inverseJoinColumns = {
					@JoinColumn(name = "C_PERMISSION_ID", referencedColumnName = "C_ID") })
	private Set<Permission> permissions = new HashSet<Permission>(0);

	@ManyToMany
	@JoinTable(name = "T_ROLE_MENU", joinColumns = {
			@JoinColumn(name = "C_ROLE_ID", referencedColumnName = "C_ID") }, inverseJoinColumns = {
					@JoinColumn(name = "C_MENU_ID", referencedColumnName = "C_ID") })
	private Set<Menu> menus = new HashSet<Menu>(0);

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getKeyword() {
		return keyword;
	}

	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Set<User> getUsers() {
		return users;
	}

	public void setUsers(Set<User> users) {
		this.users = users;
	}

	public Set<Permission> getPermissions() {
		return permissions;
	}

	public void setPermissions(Set<Permission> permissions) {
		this.permissions = permissions;
	}

	public Set<Menu> getMenus() {
		return menus;
	}

	public void setMenus(Set<Menu> menus) {
		this.menus = menus;
	}

}

4、用户

package com.itheima.bos.domain.system;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * @description:后台用户
 */
@Entity
@Table(name = "T_USER")
public class User {

	@Id
	@GeneratedValue
	@Column(name = "C_ID")
	private int id; // 主键
	@Column(name = "C_BIRTHDAY")
	private Date birthday; // 生日
	@Column(name = "C_GENDER")
	private String gender; // 性别
	@Column(name = "C_PASSWORD")
	private String password; // 密码
	@Column(name = "C_REMARK")
	private String remark; // 备注
	@Column(name = "C_STATION")
	private String station; // 状态
	@Column(name = "C_TELEPHONE")
	private String telephone; // 联系电话
	@Column(name = "C_USERNAME", unique = true)
	private String username; // 登陆用户名
	@Column(name = "C_NICKNAME")
	private String nickname; // 真实姓名

	@ManyToMany
	@JoinTable(name = "T_USER_ROLE", joinColumns = {
			@JoinColumn(name = "C_USER_ID", referencedColumnName = "C_ID") }, inverseJoinColumns = {
					@JoinColumn(name = "C_ROLE_ID", referencedColumnName = "C_ID") })
	private Set<Role> roles = new HashSet<Role>(0);

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public String getStation() {
		return station;
	}

	public void setStation(String station) {
		this.station = station;
	}

	public String getTelephone() {
		return telephone;
	}

	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getNickname() {
		return nickname;
	}

	public void setNickname(String nickname) {
		this.nickname = nickname;
	}

	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

}

5、启动项目,自动建表



三、apache shiro框架简介

1、官网

http://shiro.apache.org/


2、shiro 4大核心功能


3、shiro框架认证代码调用流程


Application Code:应用程序代码,由开发人员编写的代码

Subject:由shiro框架提供,代表当前用户对象

SecurityManager:安全管理器,由shiro框架提供,负责管理所有的Realm

Realm:安全数据桥,类似于DAO,操作权限相关的数据的

四、基于shiro框架实现后台系统的认证操作

1、在coomon-parent的pom.xml中导入shiro的jar包坐标


2、在bos_meanagement_web的web.xml中配置spring使用shiro的过滤器

注意:该过滤器一定要配置在struts2的过滤器之前

	<!-- 配置spring提供的shiro的过滤器,用于整合shiro框架的。注意:该过滤器一定要放在struts2过滤器之前 -->
	<filter>
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

3、在spring配置文件中注册shiroFilter

	<!-- 注册shiro框架的bean(过滤器) ,作用是创建shiro框架相关的一些过滤器,每个过滤器进行不同的权限校验 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 注入shiro框架核心对象,安全管理器 -->
		<property name="securityManager" ref="securityManager" />
		<!-- 
			private String loginUrl; 登录页面 
			private String successUrl; 录成功后跳转页面 
			private String unauthorizedUrl;权限不足时的提示页面 -->
		<property name="loginUrl" value="/login.html" />
		<property name="successUrl" value="/index.html" />
		<property name="unauthorizedUrl" value="/unauthorized.html" />
		<!-- 指定URL拦截规则 -->
		<property name="filterChainDefinitions">
			<!-- 
				authc:代表shiro框架提供的一个过滤器,这个过滤器用于判断当前用户是否已经完成认证, 
							如果当前用户已经认证,就放行,如果当前用户没有认证,跳转到登录页面 
				anon:代表shiro框架提供的一个过滤器,允许匿名访问 ,即可以不登录访问
				**:代表目录下的所有文件及子目录
			-->
			<value>
				/css/* = anon
				/images/* = anon
				/js/** = anon
				/validatecode.jsp* = anon
				/userAction_login.action = anon
				/** = authc
			</value>
		</property>
	</bean>

	<bean id="bosRealm" class="com.itheima.bos.shiro.BosRealm" />

	<!-- 注册安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="bosRealm" />
	</bean>

4、调整登录页面


5、创建用户登录的Action动作类

package com.itheima.bos.web.action;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.itheima.bos.domain.system.User;
import com.itheima.bos.web.action.common.CommonAction;

/**
 * 用户动作类
 * @author Administrator
 *
 */
@Controller
@Namespace("/")
@Scope("prototype")
@ParentPackage("struts-default")
public class UserAction extends CommonAction<User> {

	//定义变量,接收验证码
	private String checkcode;

	public void setCheckcode(String checkcode) {
		this.checkcode = checkcode;
	}
	
	/**
	 * 基于shiro框架实现后台系统认证
	 */
	@Action(value="userAction_login",results={
			@Result(name="home", type="redirect", location="/index.html"),
			@Result(name="login", type="redirect", location="/login.html")
	})
	public String login(){
		//从session中获取生成的验证码
		String validatecode = (String) ServletActionContext.getRequest().getSession().getAttribute("key");
		//判断输入的验证和和生成的验证码是否一致
		if(StringUtils.isNotBlank(validatecode) && StringUtils.isNotBlank(checkcode) && validatecode.equals(checkcode)){
			//输入的验证码正确,使用shiro进行认证操作
			//获取当前用户对象
			Subject subject = SecurityUtils.getSubject();
			//封装用户名密码令牌
			AuthenticationToken token = new UsernamePasswordToken(getModel().getUsername(),getModel().getPassword());
			try {
				subject.login(token);
				User user = (User) subject.getPrincipal();
				ServletActionContext.getRequest().getSession().setAttribute("loginUser", user);
				return "home";
			} catch (Exception e) {
				e.printStackTrace();
				return LOGIN;
			}
		}else{
			return LOGIN;
		}
	}
}

6、编写认证授权的realm

package com.itheima.bos.shiro;

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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.itheima.bos.dao.UserDao;
import com.itheima.bos.domain.system.User;
/**
 * 用户认证授权的方法
 * @author Administrator
 *
 */
public class BosRealm extends AuthorizingRealm {

	@Autowired
	private UserDao dao;
	/**
	 * 认证的方法
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
			throws AuthenticationException {
		UsernamePasswordToken uptoken = (UsernamePasswordToken) token;
		//获取用户输入的用户名密码
		String username = uptoken.getUsername();
		//通过用户名查询用户信息
		User user = dao.findByUsername(username);
		if(user == null){
			//没有查询到用户数据
			return null;
		}else{
			//进行密码比较
			//构造简单认证对象,参数1:用户对象,参数2:数据库中的密码,参数3:realm域名字
			AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(),this.getName());
			return info;
		}
	}

	/**
	 * 授权的方法
	 */
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection paramPrincipalCollection) {
		return null;
	}

}

7、编写用户的Dao方法

package com.itheima.bos.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.itheima.bos.domain.system.User;

public interface UserDao extends JpaRepository<User, Integer> {

	public User findByUsername(String username);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值