Как сделать Шаблонное Окно в WPF?

Хороший вопрос. Ответ более стохастичен, чем детерминированный, и я попытаюсь объяснить свое мнение, используя небольшой пример.

В сети много ссылок, которые предлагают нам использовать параметры в наших запросах или использовать хранимую процедуру с параметрами чтобы избежать SQL Injection (SQLi). Я покажу вам, что хранимые процедуры (например) не являются волшебной палочкой против SQLi. Ответственность по-прежнему остается у программиста.

Рассмотрим следующую хранимую процедуру SQL Server, которая выведет строку пользователя из таблицы «Пользователи»:

create procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
declare @sql as nvarchar(512)
set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
           'from Users '+
           'where usrUName = '''+@name+''' and usrPass = '''+@pass+''''
execute(@sql)

Вы можете получить результаты путем передачи в качестве параметров имени пользователя и пароля. Предположим, что пароль находится в свободном тексте (просто для простоты этого примера) нормальный вызов:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [dbo].[getUser] 
   @name = 'admin'
  ,@pass = '!@Th1siSTheP@ssw0rd!!'
GO

Но здесь у нас плохой метод программирования, используемый программистом внутри хранимой процедуры, поэтому злоумышленник может выполнить следующее:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [TestDB].[dbo].[getUser] 
   @name = 'admin'
  ,@pass = 'any'' OR 1=1 --'
GO

Вышеуказанные параметры будут переданы в качестве аргументов хранимой процедуры, а команда SQL, которая в конечном итоге будет выполнена, будет:

select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'

. , который получит все строки от пользователей

. Проблема в том, что даже мы следуем принципу «Создаем хранимую процедуру и передаем поля для поиска в качестве параметров», SQLi все еще выполняется. Это связано с тем, что мы просто копируем нашу плохую практику программирования внутри хранимой процедуры. Решение этой проблемы состоит в том, чтобы переписать нашу Хранимую процедуру следующим образом:

alter procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = @name and usrPass = @pass

То, что я пытаюсь сказать, заключается в том, что разработчики должны сначала узнать, что такое SQLi-атака, и как ее можно выполнить, а затем соответственно защищать их код. Слепо следовать «лучшим практикам» - это не всегда безопасный способ ... и, возможно, именно поэтому у нас так много «лучших практик» - не удается!

18
задан NoizWaves 7 January 2009 в 14:42
поделиться

4 ответа

Можно создать новый ControlTemplate, который нацелен на окно для выполнения этого как показано ниже.

<ControlTemplate x:Key="WindowControlTemplate1" TargetType="{x:Type Window}">
    <Border 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}"
        >
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="0.93*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.21*"/>
                <ColumnDefinition Width="0.79*"/>
            </Grid.ColumnDefinitions>

            <ContentPresenter 
                Grid.ColumnSpan="2" 
                Grid.Row="1" 
                Content="{TemplateBinding Content}" 
                ContentTemplate="{TemplateBinding ContentTemplate}"
                />
            <ResizeGrip 
                HorizontalAlignment="Right" 
                x:Name="WindowResizeGrip" 
                VerticalAlignment="Bottom" 
                IsTabStop="False" 
                Visibility="Collapsed" 
                Grid.Column="1" 
                Grid.Row="2"
                />
            <TextBlock Text="My Logo" />
            <TextBlock Grid.Column="1" Text="My Title"/>
            <StatusBar Height="20" Grid.ColumnSpan="2" Grid.Row="2"/>
        </Grid>
    </Border>

    <ControlTemplate.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
                <Condition Property="WindowState" Value="Normal"/>
            </MultiTrigger.Conditions>
            <Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
32
ответ дан 30 November 2019 в 07:34
поделиться

Если Вы достаточно храбры для взятия большого архитектурного сдвига, Вы могли бы рассмотреть CompositeWPF (ранее под кодовым названием Призма) от Шаблонов & парни Методов в Microsoft.

Из интереса для Вас была бы способность определить "регионы" в оболочке (т.е. окно) и затем использующие представления для заполнения регионов. Это использует шаблон Образцового Предъявителя Представления для разрешения независимой разработки "представлений" из модели, чем может быть легко перемещаться со временем, поскольку оболочка только определяет регионы и не связана непосредственно с тем, что помещается в к нему. Преимущественно это помогает отделить оболочку от представлений и представлений друг от друга и помочь модульному тесту... вздор и тому подобное.

Это - большой переход и что-то, что замедлит Вас для начала, хотя ситуация является одним из типов приложений, к которым CompositeWPF предназначен для обращения.

Как часть CompositeWPF необходимо будет принять различные шаблоны, которые могут смутить вновь прибывших, например, UnityContainer, инверсию управления, MVP (или Model/view/view-model) и внедрение зависимости.

я могу помнить, когда я сначала запустил с демонстрационных приложений, озадачиваемых, потому что не очевидно, как же некоторые представления даже создавались! Контейнер единицы инстанцирует объектов и вызовет параметризованных конструкторов волшебно.

CompositeWPF является изящным решением Вашего вопроса, но не простого или простого. Используя CompositeWPF в моем последнем проекте я намереваюсь использовать его снова для следующего соответствующего приложения.

6
ответ дан 30 November 2019 в 07:34
поделиться

Самый простой подход должен создать WPF "Страница" для окна определенные средства управления и поместить "Кадр" в главное окно. Можно даже создать хорошую навигацию этот путь.

2
ответ дан 30 November 2019 в 07:34
поделиться

почему точно Вы используете "много окон?" Почему не только единственное окно с управлением вкладкой? Или единственное окно с пользовательскими элементами управления?

Невнимательный, для ответа на вопрос usercontrols являются одним способом, которым Вы хотите получить функциональность, которую Вы описываете как желание.

Создают новый класс Окна и имеют его, имеют свойство "Childrens", которое позволяет, чтобы объект был встроен в панель прикрепления, где Вы хотите, чтобы "окно определенные средства управления" пошло.

, Поскольку Вы запускаете новые окна, инстанцируйте типа окна и пользовательского элемента управления с определенными средствами управления, добавьте пользовательский элемент управления к Дочернему свойству Вашего окна и затем покажите окно. Можно даже связать обработчики событий, DataContexts и что не в это время.

-5
ответ дан 30 November 2019 в 07:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: