JavaEE學習日誌(一百零七): ssm練習之用戶模塊實現,SpringSecurity安全框架加密

SpringSecurity

在服務端獲取用戶名

當用戶通過安全框架進行登錄後,如何在服務端獲取該用戶的用戶名?從session域中獲取登錄信息

方法一:

  1. 創建ShowUsernameController,獲取session對象
HttpSession session = request.getSession();
  1. 從session對象中獲取所有的屬性名
Enumeration attributeNames = session.getAttributeNames();
  1. 遍歷枚舉類型,通過打印結果,得知存儲在session中的屬性名。獲取到SPRING_SECURITY_CONTEXT:存儲用戶登錄信息的session中的名稱
//hasMoreElements()判斷是否有更多的元素
        //nextElement()獲取枚舉中的下一個元素
while (attributeNames.hasMoreElements()){
    System.out.println(attributeNames.nextElement());
}
  1. 獲取安全框架的上下文對象,SecurityContext對象
SecurityContext securityContext = (SecurityContext)spring_security_context;
  1. 獲取認證信息
Authentication authentication = securityContext.getAuthentication();
  1. 獲取用戶詳情信息(UserDetails對象)
//獲取重要信息,就是用戶詳情對象(UserDetails)
Object principal = authentication.getPrincipal();
User user = (User) principal;
  1. 獲取用戶名
//獲取用戶名
String username = user.getUsername();
System.out.println(username);

方法二:
直接獲得安全框架的上下文對象,然後按照上面步驟進行。此上下文對象和上述對象相同

SecurityContext context = SecurityContextHolder.getContext();

在頁面中顯示用戶名

方法一:EL表達式,可以和上述步驟進行對應

${sessionScope.SPRING_SECURITY_CONTEXT.authentication.principal.username}

方法二:security標籤庫,首先引入security的標籤庫

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<security:authentication property="principal.username" />

在這裏插入圖片描述

退出操作

點擊註銷之後,清空session,並跳轉login頁面
在這裏插入圖片描述
之前已經配置過了

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

所以直接修改訪問路徑即可

<div class="pull-right">
	<a href="${pageContext.request.contextPath}/logout"
		class="btn btn-default btn-flat">註銷</a>
</div>

用戶模塊

查詢所有用戶

在這裏插入圖片描述

UserController

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserService userService;
    @RequestMapping("/findAll")
    public ModelAndView findAll(){
        //查詢數據
        List<SysUser> userList = userService.findAll();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("userList",userList);
        modelAndView.setViewName("user-list");
        return modelAndView;
    }
}

UserService

@Override
    public List<SysUser> findAll() {
        return userDao.findAll();
    }

UserDao

/**
     * 查詢全部用戶
     * @return
     */
    @Select("select * from sys_user")
    List<SysUser> findAll();

前端

<tbody>

	<c:forEach items="${userList}" var="user">
		<tr>
			<td><input name="ids" type="checkbox"></td>
			<td>${user.id }</td>
			<td>${user.username }</td>
			<td>${user.email }</td>
			<td>${user.phoneNum }</td>
			<td>${user.status==1?"激活":"未激活" }</td>
			<td class="text-center">
				<a href="${pageContext.request.contextPath}/pages/user-show.jsp" class="btn bg-olive btn-xs">詳情</a>
				<a href="${pageContext.request.contextPath}/pages/user-role-add.jsp" class="btn bg-olive btn-xs">添加角色</a>
			</td>
		</tr>
	</c:forEach>
</tbody>

添加用戶

在這裏插入圖片描述

UserController

/**
     * 保存用戶
     * @param user
     * @return
     */
    @RequestMapping("/save")
    public String save(SysUser user){
        userService.save(user);
        return "redirect:/user/findAll";
    }

UserService

@Override
    public void save(SysUser user) {
        userDao.save(user);
    }

UserDao

/**
     * 保存用戶
     * @param user
     */
    @Insert("insert into sys_user values(user_seq.nextval,#{username},#{email},#{password},#{phoneNum},#{status})")
    void save(SysUser user);

md5密碼加密

md5加密工具類

package com.itheima.utils;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Utils {
	/**
	 * 使用md5的算法進行加密
	 */
	public static String md5(String plainText) {
		byte[] secretBytes = null;
		try {
			secretBytes = MessageDigest.getInstance("md5").digest(
					plainText.getBytes());
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("沒有md5這個算法!");
		}
		String md5code = new BigInteger(1, secretBytes).toString(16);// 16進制數字
		// 如果生成數字未滿32位,需要前面補0
		for (int i = 0; i < 32 - md5code.length(); i++) {
			md5code = "0" + md5code;
		}
		return md5code;
	}

	public static void main(String[] args) {
		System.out.println(md5("123"));
	}

}

添加用戶方法加密

@Override
    public void save(SysUser user) {
        //獲取明文密碼
        String password = user.getPassword();
        //對明文密碼進行加密
        String md5Password = MD5Utils.md5(password);
        //把加密後的密碼存儲到user對象中
        user.setPassword(md5Password);
        userDao.save(user);
    }

當輸入密碼爲123時,就會進行加密操作
在這裏插入圖片描述
但會出現一個問題,相同的密碼加密後的密文相同

SpringSecurity密碼加密

在md5的基礎上,把一個隨機數作爲密鑰生成密文

一、在spring-security.xml中添加配置,創建加密工具類對象

<!--創建加密工具類對象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>

二、自動注入

@Autowired
PasswordEncoder passwordEncoder;

三、加密

 @Override
    public void save(SysUser user) {
        //獲取明文密碼
        String password = user.getPassword();
        //對明文密碼進行加密
        String securityPassword = passwordEncoder.encode(password);
        //把加密後的密碼存儲到user對象中
        user.setPassword(securityPassword);
        userDao.save(user);
    }

在這裏插入圖片描述

SpringSecurity登錄細節實現

雖然進行了加密,但加密後的密碼無法使用原密碼登錄,所以登錄還要細節沒有完成

一、在spring-security.xml中添加一句

 <security:password-encoder ref="passwordEncoder"></security:password-encoder>

添加之後

<!-- 配置認證(登錄)信息:認證管理器 -->
    <security:authentication-manager>
        <!--認證信息的提供者:關聯用戶服務對象,提供賬號和密碼-->
        <security:authentication-provider user-service-ref="userServiceImpl">
            <!--指定加密工具類-->
            <security:password-encoder ref="passwordEncoder"></security:password-encoder>
            <!--&lt;!&ndash;用戶服務對象&ndash;&gt;
            <security:user-service>
                &lt;!&ndash;用戶信息:臨時的賬號和密碼
                    {noop}:不使用加密
                    authorities:指定用戶的認證角色
                &ndash;&gt;
                <security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
            </security:user-service>-->

        </security:authentication-provider>
    </security:authentication-manager>

二、將UserDetails中的{noop}去除

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根據用戶名獲取用戶(SysUser)對象
        SysUser sysUser = userDao.findByUsername(username);
        System.out.println(username);
        System.out.println(sysUser);
        if(sysUser!=null){
            //創建角色集合對象
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            //創建臨時角色對象
            SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
            //對象添加到集合中
            authorities.add(grantedAuthority);
            /**
             * 參數1:username
             * 參數2:password
             * 參數3:角色列表對象
             */
            UserDetails user = new User(sysUser.getUsername(),sysUser.getPassword(),authorities);
            return user;
        }

        return null;

    }

注意細節:先配置認證信息,再創建加密工具類

解析標籤security:authentication-provider,判斷該標籤中是否存在子標籤security:password-encoder‘

  • 如果有此子標籤,則使用指定密碼加密工具類
  • 如果沒有此子標籤,則從spring容器中查詢名稱爲passwordEncoder,的加密工具類,使用從容器中獲取的工具類
<!-- 配置認證(登錄)信息: 認證管理器 -->
    <security:authentication-manager>
        <!--認證信息的提供者: 關聯用戶服務對象-提供賬號和密碼-->
        <!--
            解析標籤security:authentication-provider,判斷該標籤中是否存在子標籤security:password-encoder‘
            如果有此子標籤,則使用指定密碼加密工具類
            如果沒有此子標籤,則從spring容器中查詢名稱爲passwordEncoder,的加密工具類,使用從容器中獲取的工具類

        -->
        <security:authentication-provider user-service-ref="userService">
            <!--指定登錄加密工具類-->
            <security:password-encoder ref="passwordEncoder"></security:password-encoder>
            <!--用戶的服務對象-->
            <!--<security:user-service>-->
                <!--用戶信息:是臨時賬號和密碼-->
                <!--{noop}: 不使用加密-->
                <!--authorities: 指定用戶的認證角色-->
                <!--<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <!--創建一個加密工具類-->
    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章