练手项目1笔记 day04

目标

  • 实现springsecurity的入门小demo
  • 完成运营商登录与安全控制功能
  • 完成商家入驻
  • 完成商家审核
  • 完成商家系统登录与安全控制功能

1. 和之前的比较

1. jar包比较

ssm项目中引入的jar包
<dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring.security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${spring.security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${spring.security.version}</version>
        </dependency>
本次jar包
<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>4.1.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>4.1.0.RELEASE</version>
		</dependency>

少了spring-security-core,maven导包时自动导入了。没用taglibs

2. web.xml

都一样

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring-security.xml</param-value>
	 </context-param>
	 <listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	 </listener>
	
	 <filter>  
		<filter-name>springSecurityFilterChain</filter-name>  
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
	 </filter>  
	 <filter-mapping>  
		<filter-name>springSecurityFilterChain</filter-name>  
		<url-pattern>/*</url-pattern>  
	 </filter-mapping>

3. spring-security.xml

ssm项目
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled"/>

    <!--配置不拦截的资源-->
    <security:http pattern="/login.jsp" security="none"/>
    <security:http pattern="/failer.jsp" security="none"/>
    <security:http pattern="/css/**" security="none"/>
    <security:http pattern="/img/**" security="none"/>
    <security:http pattern="/plugins/**" security="none"/>

    <!--
    配置具体的规则
    auto-config="true" 不用自己编写登录的页面,框架提供默认登录页面
    use-expressions="false" 是否使用SPEL表达式
    -->
    <security:http auto-config="true" use-expressions="true">
        <!--配置具体的拦截的规则 pattern="请求路径的规则"
        access="访问系统的人,必须有ROLE_USER的角色"-->
        <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>

        <!--定义跳转的具体的页面-->
        <security:form-login
            login-page="/login.jsp"
            login-processing-url="/login.do"
            default-target-url="/index.jsp"
            authentication-failure-url="/failer.jsp"
            authentication-success-forward-url="/pages/main.jsp"
        />

        <!--关闭跨域请求-->
        <security:csrf disabled="true"/>

        <!--退出-->
        <security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp"/>
    </security:http>

    <!--认证管理器,切换成数据库中的用户名和密码-->
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="userService">
            <!--配置加密的方式-->
            <security:password-encoder ref="passwordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <!--配置加密类-->
    <!--bcrypt,是一个跨平台的文件加密工具。-->
    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

</beans>

采用数据库的users表

在这里插入图片描述

对应实体类UserInfo

public class UserInfo {

    private String id;
    private String username;
    private String email;
    private String password;
    private String phoneNum;
    private int status; // 状态0 未开启 1 开启
    private String statusStr;
    private List<Role> roles;
//...

角色表role

在这里插入图片描述

剩余部分见之前分析。

项目中的直接看本次项目

2. 运营商系统登录与安全控制

1. 登录功能的实现

1. 配置文件

修改pinyougou-manager-web的pom.xml文件,添加依赖

修改web.xml,和之前项目一样

pinyougou-manager-web的spring目录下添加配置文件spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <!--设置页面不登录也能访问-->
    <http pattern="/*.html" security="none"/>
    <http pattern="/css/**" security="none"/>
    <http pattern="/img/**" security="none"/>
    <http pattern="/js/**" security="none"/>
    <http pattern="/plugins/**" security="none"/>

    <!--页面的拦截规则-->
    <http use-expressions="false">
        <intercept-url pattern="/**" access="ROLE_ADMIN"/>
        <form-login login-page="/login.html" default-target-url="/admin/index.html"
                    authentication-failure-url="/login.html" always-use-default-target="true"/>
        <csrf disabled="true"/>
        <headers>
            <frame-options policy="SAMEORIGIN"/>
        </headers>
        <logout/>
    </http>

    <!--认证管理器-->
    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="admin" password="123" authorities="ROLE_ADMIN"/>
                <user name="tom" password="123" authorities="ROLE_ADMIN"/>
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

always-use-default-target指定是否在身份验证通过后总是跳转到default-target-url属性指定的url

如果使用了iframe,需要设置框架页的策略为SAMEORIGIN

2. login.html
<form class="sui-form" action="/login" method="post" id="loginForm">
  <div class="input-prepend"><span class="add-on loginname"></span>
    <input id="prependedInput" name="username" type="text" placeholder="邮箱/用户名/手机号" class="span2 input-xfat">
  </div>
  <div class="input-prepend"><span class="add-on loginpwd"></span>
    <input id="prependedInput" name="password" type="password" placeholder="请输入密码" class="span2 input-xfat">
  </div>
  <a class="sui-btn btn-block btn-xlarge btn-danger" onclick="document:loginForm.submit()" target="_blank">&nbsp;&nbsp;</a>
3. 主界面显示登录user
1. 新建loginController.java
@RestController
@RequestMapping("/login")
public class LoginController {

    @RequestMapping("/getName")
    public Map getName(){
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        Map map = new HashMap();
        map.put("loginName",name);
        return map;
    }
}
2. 新建loginService.js
// 登录服务层

app.service('loginService',function ($http) {
    this.loginName = function () {
        return $http.get('../login/getName.do');
    }
});
3. 新建indexController.js
app.controller('indexController',function ($scope,$controller, loginService) {

    // 显示当前用户名
    $scope.showLoginName = function () {
        loginService.loginName().success(
            function (response) {
                $scope.loginName = response.loginName;
            }
        );
    }
});
4. 页面引入js
    <script src="../plugins/adminLTE/js/app.min.js"></script>

    <script src="../plugins/angularjs/angular.min.js"></script>
    <script type="text/javascript" src="../js/base.js"></script>
    <script type="text/javascript" src="../js/service/loginService.js"></script>
    <script type="text/javascript" src="../js/controller/indexController.js"></script>

指令

<body class="hold-transition skin-green sidebar-mini" ng-app="pinyougou" ng-controller="indexController" ng-init="showLoginName()">

将页面的测试用户,替换为{{loginName}}

4. 退出登录

在pinyougou-manager-web的spring-security.xml的http节点天啊及配置

<logout/>

修改注销的链接

 <a href="../logout" class="btn btn-default btn-flat">注销</a>

2. 商家申请入驻

1. 需求分析

需要填写商家相关的信息,运营商平台审核通过后可以使用

2. 准备工作
  1. 拷贝静态资源到pinyougou-shop-web工程
  2. 参照运营商后台构建js controller的base goods和seller;service的goods和seller
  3. 拷贝后端控制层代码 GoodsController和SellerController
3. 前端代码

修改register.html,引入js

	<script src="plugins/angularjs/angular.min.js"></script>

	<script type="text/javascript" src="js/base.js"></script>
	<script type="text/javascript" src="js/service/sellerService.js"></script>
	<script type="text/javascript" src="js/controller/sellerController.js"></script>
	<script type="text/javascript" src="js/controller/baseController.js"></script>

指令

<body ng-app="pinyougou" ng-controller="sellerController">

绑定表单

将对应的都更改

<input type="text" placeholder="登陆名" ng-model="entity.sellerId" class="input-xfat input-xlarge">
...

修改sellerController.js,保存成功后跳转到登录页

	//新增
	$scope.add=function(){
		sellerService.add($scope.entity).success(
			function(response){
				if(response.success){
					//如果注册成功,跳转登录页面
					location.href="shoplogin.html";
				}else{
					alert(response.message);
				}
			}
		);
	}

绑定“申请入驻”按钮

<a class="sui-btn btn-block btn-xlarge btn-danger" ng-click="add()" target="_blank">申请入驻</a>
4. 后端代码

修改后端SellerServiceImpl的add方法,设置状态为0

	@Override
	public void add(TbSeller seller) {
		seller.setCreateTime(new Date());// 申请日期
		seller.setStatus("0");// 状态
		sellerMapper.insert(seller);		
	}

3. 商家审核

1. 需求分析

网站运营人员在运营商后台进行审核,审核后商家才能登录系统

状态包括:0 未审核 1 已审核 2 审核未通过 3 关闭

2. 商家待审核列表

修改seller_1.html,引入js

	<script src="../plugins/angularjs/angular.min.js"></script>

	<!--分页组件开始-->
	<script src="../plugins/angularjs/pagination.js"></script>
	<link rel="stylesheet" href="../plugins/angularjs/pagination.css">
	<!--分页组件结束-->
	<script type="text/javascript" src="../js/base_pagination.js"></script>
	<script type="text/javascript" src="../js/service/sellerService.js"></script>
	<script type="text/javascript" src="../js/controller/sellerController.js"></script>
	<script type="text/javascript" src="../js/controller/baseController.js"></script>

指令

<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="sellerController" ng-init="searchEntity={status:'0'}">

加入分页控件

<tm-pagination conf="paginationConf"></tm-pagination>

循环

<tr ng-repeat="entity in list">
  <td><input  type="checkbox"></td>			                              
  <td>{{entity.sellerId}}</td>
  <td>{{entity.name}}</td>
  <td>{{entity.nickName}}</td>
  <td>{{entity.linkmanName}}</td>
  <td>{{entity.telephone}}</td>
3. 商家详情
1. 绑定页面弹出窗口
<!-- 选项卡开始 -->         
<div id="myTabContent" class="tab-content">
  <div class="tab-pane active in" id="home">
    <br>
    <table class="table table-bordered table-striped"  width="800px">
      <tr>
        <td>公司名称</td>
        <td>{{entity.name}}</td>
      </tr>
      <tr>
        <td>店铺名称</td>
        <td>{{entity.nickName}}</td>
        ...
2. 绑定详情按钮
<button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#sellerModal" ng-click="findOne(entity.sellerId)">详情</button>
4. 商家审核
1. 后端代码

seller-goods-interface工程的SellerService.java新增方法

public void updateStatus(String sellerId, String status);

sellergoods-service的SellerServiceImpl.java新增方法

 @Override
    public void updateStatus(String sellerId, String status) {
        TbSeller seller = sellerMapper.selectByPrimaryKey(sellerId);
        seller.setStatus(status);
        sellerMapper.updateByPrimaryKey(seller);
    }

manager-web的SellerController.java新增方法

	@RequestMapping("/updateStatus")
	public Result updateStatus(String sellerId, String status){
		try {
			sellerService.updateStatus(sellerId,status);
			return new Result(true,"成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false,"失败");
		}
	}
2. 前端代码

修改manager-web的sellerService.js

// 更新状态
	this.updateStatus = function (sellerId,status) {
		return $http.get('../seller/updateStatus.do?sellerId='+sellerId+'&status='+status);
	}

修改selllerController.js

	// 更改状态
	$scope.updateStatus = function (sellerId, status) {
		sellerService.updateStatus(sellerId, status).success(
			function (response) {
				if(response.success){
					$scope.reloadList();
				}else{
					alert(response.message);
				}
			}
		);
	}

修改按钮,调用方法

<button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="updateStatus(entity.sellerId,'1')">审核通过</button>
         	<button class="btn btn-danger"  data-dismiss="modal" aria-hidden="true" ng-click="updateStatus(entity.sellerId,'2')">审核未通过</button>
            <button class="btn btn-danger" data-dismiss="modal" aria-hidden="true" ng-click="updateStatus(entity.sellerId,'3')">关闭商家</button>

3. 商家系统登录和安全控制

1. 需求分析

完成商家系统登录和安全控制,商家账号来自数据库,实现密码加密

2. 自定义认证类

1. 配置文件

pom.xml、web.xml、shoplogin.html参照运营商管理后台

2. UserDetailsServiceImpl

在shop-web下创建com.pinyougou.service包,包下创建类UserDetailsServiceImpl.java实现UserDetailsService接口

注意最好不要用注解,set方法注入sellerService

public class UserDetailsServiceImpl implements UserDetailsService {

    private SellerService sellerService;

    public void setSellerService(SellerService sellerService) {
        this.sellerService = sellerService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("经过了UserDetailsServiceImpl");

        // 构建角色列表
        List<GrantedAuthority> grantAuths = new ArrayList<>();
        grantAuths.add(new SimpleGrantedAuthority("ROLE_SELLER"));

        // 得到商家对象
        TbSeller seller = sellerService.findOne(username);
        if(seller!=null){
            if(seller.getStatus().equals("1")){
                return new User(username,seller.getPassword(),grantAuths);
            }else{
                return null;
            }
        }else{
            return null;
        }
    }
}
3. 创建spring-security.xml

模仿运营商部分

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
             xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <!--设置页面不登录也能访问-->
    <http pattern="/*.html" security="none"/>
    <http pattern="/css/**" security="none"/>
    <http pattern="/img/**" security="none"/>
    <http pattern="/js/**" security="none"/>
    <http pattern="/plugins/**" security="none"/>
    <http pattern="/seller/add.do" security="none"/>

    <!--页面的拦截规则-->
    <http use-expressions="false">
        <intercept-url pattern="/**" access="ROLE_SELLER"/>
        <form-login login-page="/shoplogin.html" default-target-url="/admin/index.html"
                    authentication-failure-url="/shoplogin.html" always-use-default-target="true"/>
        <csrf disabled="true"/>
        <headers>
            <frame-options policy="SAMEORIGIN"/>
        </headers>
        <logout/>
    </http>

    <!--认证管理器-->
    <authentication-manager>
        <authentication-provider user-service-ref="userDetailService">
            <password-encoder ref="bCryptPasswordEncoder"/>
        </authentication-provider>
    </authentication-manager>

    <!--认证类-->
    <beans:bean id="userDetailService" class="com.pinyougou.service.UserDetailsServiceImpl">
        <beans:property name="sellerService" ref="sellerService"/>
    </beans:bean>

    <!-- 引用dubbo 服务 -->
    <dubbo:application name="pinyougou-shop-web" />
    <dubbo:registry address="zookeeper://192.168.25.128:2181"/>
    <dubbo:reference interface="com.pinyougou.sellergoods.service.SellerService" id="sellerService"/>

    <beans:bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans:beans>

3. 认证类调用服务方法

修改UserDetailsServiceImpl.java,添加属性和setter方法,修改loadUserByUsername方法

调用SellerService

修改shop-web的spring-security.xml,添加配置 dubbo的sellerService

4. 密码加密

BCrypt算法加盐,防止MD5被彩虹表破解

1. 商家入驻密码加密

修改SellerController.java的add方法

	@RequestMapping("/add")
	public Result add(@RequestBody TbSeller seller){
		// 密码加密
		BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
		String password = bCryptPasswordEncoder.encode(seller.getPassword());//加密
		seller.setPassword(password);

		try {
			sellerService.add(seller);
			return new Result(true, "增加成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "增加失败");
		}
	}
2. 加密配置

修改spring-security.xml,添加配置

bcryptEncoder的bean以及将其配置到认证管理器

5. 显示登录名

同运营商

6. 退出登录

同运营商

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值