使用SSM整合shiro安全框架

1. shiro的密码加密

在这里插入图片描述

2. shiro整合ssm完成认证和授权的功能

  • 建立maven项目
    在这里插入图片描述
  • (1)添加相对应依赖(根据需要也可再添加其他依赖)
<properties>
		<servlet.version>3.1.0</servlet.version>
		<jsp.version>2.3.1</jsp.version>
		<spring.version>4.3.24.RELEASE</spring.version>
		<mybatis.version>3.5.1</mybatis.version>
	<mybatis.spring.version>2.0.1</mybatis.spring.version>
		<mysql.version>5.1.47</mysql.version>
		<pagehelper.version>5.1.10</pagehelper.version>
		<druid.version>1.1.19</druid.version>
		<log4j.version>1.2.17</log4j.version>
		<slf4j.version>1.7.26</slf4j.version>
		<jackson.version>2.9.9</jackson.version>
		<shiro.version>1.4.1</shiro.version>
	</properties>
	<dependencies>
		<!--servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>${servlet.version}</version>
			<scope>provided</scope>
		</dependency>
		<!-- javax.servlet.jsp -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>${jsp.version}</version>
			<scope>provided</scope>
		</dependency>
		<!--spring-core -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${mybatis.version}</version>
		</dependency>
		<!-- mybatis-spring -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>${mybatis.spring.version}</version>
		</dependency>
		<!-- mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql.version}</version>
		</dependency>
		<!-- pagehelper -->
		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper</artifactId>
			<version>${pagehelper.version}</version>
		</dependency>
		<!-- druid -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>${druid.version}</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>${log4j.version}</version>
		</dependency>
		<!-- slf4j-api -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
		</dependency>
		<!-- jackson-core -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>
	</dependencies>
  • (2)spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--包扫描-->
    <context:component-scan base-package="com.fyx.service"/>
    <!--配置数据库据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"/>
        <property name="password" value="123@qwe"/>//密码
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/shiro"/>
    </bean>

    <!--SqlSessionFactoryBean-->
    <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!--为Dao生成实现类 mybatis-plus-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.fyx.dao"/>
    </bean>

    <!--事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--开启事务的注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--spring整合shiro-->
    <!--创建SecurityManager-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="myRealm"/>
    </bean>

    <!--创建realm对象-->
    <bean id="myRealm" class="com.fyx.realm.MyRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>

    <!--创建密码匹配器-->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <property name="hashAlgorithmName" value="MD5"/>
        <property name="hashIterations" value="1024"/>
    </bean>
    <!--设置shiro的过滤规则
           该id值有一定的意义。
    -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/tologin"/>
        <!--如果没有认证 则跳转到登陆界面
        <property name="loginUrl" value="/tologin"/>
        -->
        <!--如果没有授权则跳转的页面-->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!--anon:表示允许匿名访问
            authc:需要认证后才可以访问
        -->
        <property name="filterChainDefinitions">
            <value>
                /index.jsp=anon
                /login=anon
                /static/**=anon
                /**=authc
            </value>
        </property>
    </bean>
    <bean id="myFilter" class="com.fyx.filter.LoginFilter"></bean>
</beans>

  • (3)springmvc的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--包扫描-->
    <context:component-scan base-package="com.fyx.controller"/>

    <!--静态资源放行-->
    <mvc:default-servlet-handler/>

    <!--注解驱动-->
    <mvc:annotation-driven/>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

  <welcome-file-list>
    <welcome-file>/views/login.jsp</welcome-file>
  </welcome-file-list>
  <!--配置shiro的过滤器-->
  <filter>
    <!--必须和shiro的过滤规则的id一致-->
    <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>

  <!--监听器-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:application.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--前端控制器-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
  • (5)controller层 service层 dao层 entity层

entity层

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer userid;
    private String username;
    private String userpwd;
    private String  sex;
    private String  address;
    private String  salt;//盐
}
  • dao层

UserDao类

public interface UserDao {
      /**
     * 根据用户名查询用户信息
     * @param username
     * @return
     */
    User selectByUsername(@Param("username") String username);
}

PermissionDao类

public interface PermissionDao {
	/**
	*根据userid查询用户对应权限
	/
    List<String> findAllPermissionByUserId(Integer userid);
}
  • service层

UserService类

public interface  UserService {
	/**
	*根据用户名查询用户信息
	/
    User selectByUsername(String username);
}

PermissionService类

public interface PermissionService {
    List<String> findAllPermissionByUserId(Integer userid);
}
  • service层-impl层

UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;

    public User findByUsername(String username) {
        return userDao.selectByUsername(username);
    }
}

PermissionServiceImpl类

@Service
public class PermissionServiceImpl implements PermissionService {
    @Resource
    private PermissionDao permissionDao;
    public List<String> findAllPermissionByUserId(Integer userid) {
        return permissionDao.findAllPermissionByUserId(userid);
    }
}

  • controller层

PageController类

@Controller
public class PageController {

    @GetMapping("tologin")
    public String tologin(){
        return "login";
    }
}

LoginController类

@Controller

public class LoginController {

    @PostMapping("login")
    public String login(String username,String userpwd){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,userpwd);
        try{
            subject.login(token);//登录成功转发到成功页面
            return "success";
        }catch (Exception e){
            return "redirect:/tologin";//重定向到登录页面
        }
    }
}

UserController类

@RestController
@RequestMapping("user")
public class UserController {

    @GetMapping("query")
    @RequiresPermissions("user:query")
    public String query(){
        return "user:query";
    }
    @GetMapping("delete")
    @RequiresPermissions("user:delete")
    public String delete(){
        return "user:delete";
    }

    @GetMapping("update")
    @RequiresPermissions("user:update")
    public String update(){
        return "user:update";
    }

    @GetMapping("insert")
    @RequiresPermissions("user:insert")
    public String insert(){
        return "user:insert";
    }

    @GetMapping("export")
    @RequiresPermissions("user:export") //@Transcational
    public String export(){
        return "user:export";
    }
}

MyHandlerController类
这个是用来处理项目中的异常,如果报相应的异常,就会执行相应的逻辑,注意类上使用的注解

@ControllerAdvice
public class MyHandlerException {

    @ExceptionHandler(value = UnauthorizedException.class)
    public void unauthorizedException(){
        System.out.println("quanxianbugou");
    }
}

  • (6)映射文件

UserMapper.xml文件

<?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.fyx.dao.UserDao">

    <select id="selectByUsername" resultType="com.fyx.entity.User">
        select * from user where username=#{username}
    </select>
</mapper>

PermissionMapper.xml文件

<?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.fyx.dao.PermissionDao">

    <select id="findAllPermissionByUserId" resultType="java.lang.String">
        select percode from user_role ur,role_permission rp, permission p
        where ur.roleid=rp.roleid and rp.perid=p.perid and ur.userid=#{userid}
    </select>
</mapper>
  • realm(授权认证)

MyRealm类

public class MyRealm extends AuthorizingRealm {
    @Resource
    private UserService userService;
    @Resource
    private PermissionService permissionService;

    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取认证后的用户信息
        User user = (User)principals.getPrimaryPrincipal();
        //根据用户id查询对应的权限
        List<String> userId = permissionService.findAllPermissionByUserId(user.getUserid());

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if(userId.size()>0){
            info.addStringPermissions(userId);
        }
        return info;
    }

    /**
     * 认证功能
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取账号
        String username = token.getPrincipal().toString();
        //调用根据用户名查询用户信息的方法
        User user = userService.findByUsername(username);
        if (user!=null){
            ByteSource salt = ByteSource.Util.bytes(user.getSalt());
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getUserpwd(), salt, this.getName());
            return info;
        }
        return null;
    }
}
  • (7)创建jsp页面

① login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
<h1>登陆页面</h1>
<form action="${pageContext.request.contextPath}/login" method="post">
    账号:<input type="text" name="username"/><br>
    密码:<input type="text" name="userpwd"/><br>
    <input type="submit" value="登陆"/>
    <input type="button" value="注册" onclick="location.href='regist'"/>
</form>
</body>
</html>

② success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
登陆成功  <h1>欢迎来到129班 尽情欢呼!</h1>
<shiro:hasPermission name="user:query">
    <a href="/user/query">查询所有用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:update">
    <a href="/user/update">修改用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:delete">
    <a href="/user/delete">删除用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:insert">
    <a href="/user/insert">添加用户</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="user:export">
    <a href="/user/export">导出用户</a><br>
</shiro:hasPermission>
</body>
</html>

③ index.jsp

<html>
<body>
<h2>Hello World!</h2>
<jsp:forward page="/tologin"></jsp:forward>
</body>
</html>

④ unauthorized.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>该用户没有权限</h1>
</body>
</html>
  • 测试
    在这里插入图片描述
    在这里插入图片描述

3. shiro整合ssm完成前后端完全分离(json类型)

前后端完全分离的模式:对于前端的请求,后台不再跳转页面,而是返回给请求者一个json数据。

该项目中有三个地方需要改造返回json数据:
1、认证成功或认证失败时
2、出现异常时,例如权限不足时
3、未登录访问时
因为用到了转化json数据,所以还要导入依赖

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.62</version>
</dependency>
  • 创建返回的json数据格式 Result类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Integer code;
    private String msg;
    private Object data;
}
  • 改造Controller

将Controller层的@Controller都改成@RestController,将@ControllerAdvice改成@RestControllerAdvice

① LoginController类

 @PostMapping("login")
    public Result login(String username, String userpwd){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,userpwd);
             try {
            subject.login(token);//开始认证
            Object principal = subject.getPrincipal();
            return new Result(200,"登录成功",principal);
        }catch (Exception e){
            return new Result(500,"登录失败",null);
        }
    }

② MyHandlerController类

@RestControllerAdvice
public class MyHandlerException {

    @ExceptionHandler(value = UnauthorizedException.class)
    public CommonResult unauthorizedException(){
        return new CommonResult(5001,"权限不足",null);
    }
}

③未登录访问时:有两种改造方法
1、更改PageController

@RestController
public class PageController {
    @GetMapping("/tologin")
    public CommonResult loginPage(){
        return new CommonResult(5002,"请先登录",null);
    }
}

第二种:更改spirng配置文件,实现一个自己的过滤器
1、修改spring配置文件

 <!--设置shiro的过滤规则
           该id值有一定的意义。
    -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
          <property name="securityManager" ref="securityManager"/>
          <!--如果没有认证 则跳转到登陆界面
          <property name="loginUrl" value="/tologin"/>
          -->
          <!--如果没有授权则跳转的页面-->
          <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!--anon:表示允许匿名访问
            authc:需要认证后才可以访问
        -->
          <property name="filterChainDefinitions">
              <value>
                  /index.jsp=anon
                  /login=anon
                  /static/**=anon
                  /**=authc
              </value>
          </property>

        <!--配置自己的过滤器-->
        <property name="filters">
             <map>
                  <entry key="authc" value-ref="myFilter"/>
             </map>
        </property>
    </bean>
    <bean id="myFilter" class="com.fy.filter.LoginFilter"></bean>

2、创建Filter类

public class LoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        Result commonResult=new Result(500,"未登录",null);
        writer.print(JSON.toJSONString(commonResult));
        return false;
    }
}
  • 测试
    在这里插入图片描述
    登录成功

在这里插入图片描述

登录失败

在这里插入图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值